From ba4d2ff4805cf9fe83e2919c8609481fb7495cf0 Mon Sep 17 00:00:00 2001 From: nickAS21 <44275303+nickAS21@users.noreply.github.com> Date: Fri, 26 Mar 2021 17:32:26 +0200 Subject: [PATCH] lwm2m: notification in transport, add, update, del models (#4309) * lwm2m: notification in transport, add, update, del models * lwm2m: notification in transport, add, update, del models2 --- .../common/data/lwm2m/LwM2mInstance.java | 2 +- ...esource.java => LwM2mResourceObserve.java} | 4 +- .../lwm2m/server/LwM2mSessionMsgListener.java | 15 +++- .../lwm2m/server/LwM2mTransportRequest.java | 19 +++-- .../lwm2m/server/LwM2mTransportService.java | 4 + .../server/LwM2mTransportServiceImpl.java | 76 ++++++++++------- .../server/LwM2mVersionedModelProvider.java | 2 +- .../lwm2m/server/client/LwM2mClient.java | 82 +++++++++++++++++-- .../server/client/LwM2mClientProfile.java | 12 +-- .../lwm2m/server/client/ResourceValue.java | 21 ++--- .../common/transport/SessionMsgListener.java | 13 +-- .../lwm2m/LwM2MTransportConfigServer.java | 12 --- .../service/DefaultTransportService.java | 13 ++- .../dao/resource/BaseTbResourceService.java | 14 ++-- 14 files changed, 191 insertions(+), 98 deletions(-) rename common/data/src/main/java/org/thingsboard/server/common/data/lwm2m/{LwM2mResource.java => LwM2mResourceObserve.java} (92%) diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/lwm2m/LwM2mInstance.java b/common/data/src/main/java/org/thingsboard/server/common/data/lwm2m/LwM2mInstance.java index aeff342582..1e0ff70e8a 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/lwm2m/LwM2mInstance.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/lwm2m/LwM2mInstance.java @@ -20,6 +20,6 @@ import lombok.Data; @Data public class LwM2mInstance { int id; - LwM2mResource [] resources; + LwM2mResourceObserve[] resources; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/lwm2m/LwM2mResource.java b/common/data/src/main/java/org/thingsboard/server/common/data/lwm2m/LwM2mResourceObserve.java similarity index 92% rename from common/data/src/main/java/org/thingsboard/server/common/data/lwm2m/LwM2mResource.java rename to common/data/src/main/java/org/thingsboard/server/common/data/lwm2m/LwM2mResourceObserve.java index 9317232b9d..402309ebf3 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/lwm2m/LwM2mResource.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/lwm2m/LwM2mResourceObserve.java @@ -22,7 +22,7 @@ import java.util.stream.Stream; @Data @AllArgsConstructor -public class LwM2mResource { +public class LwM2mResourceObserve { int id; String name; boolean observe; @@ -30,7 +30,7 @@ public class LwM2mResource { boolean telemetry; String keyName; - public LwM2mResource(int id, String name, boolean observe, boolean attribute, boolean telemetry) { + public LwM2mResourceObserve(int id, String name, boolean observe, boolean attribute, boolean telemetry) { this.id = id; this.name = name; this.observe = observe; diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mSessionMsgListener.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mSessionMsgListener.java index 15fb015f32..20baeba453 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mSessionMsgListener.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mSessionMsgListener.java @@ -20,10 +20,11 @@ import io.netty.util.concurrent.GenericFutureListener; import lombok.extern.slf4j.Slf4j; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.DeviceProfile; +import org.thingsboard.server.common.data.ResourceType; import org.thingsboard.server.common.transport.SessionMsgListener; import org.thingsboard.server.gen.transport.TransportProtos; -import org.thingsboard.server.gen.transport.TransportProtos.GetAttributeResponseMsg; import org.thingsboard.server.gen.transport.TransportProtos.AttributeUpdateNotificationMsg; +import org.thingsboard.server.gen.transport.TransportProtos.GetAttributeResponseMsg; import org.thingsboard.server.gen.transport.TransportProtos.SessionCloseNotificationProto; import org.thingsboard.server.gen.transport.TransportProtos.ToDeviceRpcRequestMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToServerRpcResponseMsg; @@ -85,4 +86,16 @@ public class LwM2mSessionMsgListener implements GenericFutureListener future) throws Exception { log.info("[{}] operationComplete", future); } + + public void onResourceUpdate(Optional resourceUpdateMsgOpt) { + if (ResourceType.LWM2M_MODEL.name().equals(resourceUpdateMsgOpt.get().getResourceType())) { + this.service.onResourceUpdate(resourceUpdateMsgOpt); + } + } + + public void onResourceDelete(Optional resourceDeleteMsgOpt) { + if (ResourceType.LWM2M_MODEL.name().equals(resourceDeleteMsgOpt.get().getResourceType())) { + this.service.onResourceDelete(resourceDeleteMsgOpt); + } + } } 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 cae3eeb05d..217d829c6a 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 @@ -83,7 +83,7 @@ public class LwM2mTransportRequest { private LwM2mValueConverterImpl converter; - private final LwM2mTransportContextServer context; + private final LwM2mTransportContextServer lwM2mTransportContextServer; private final LwM2mClientContext lwM2mClientContext; @@ -91,8 +91,8 @@ public class LwM2mTransportRequest { private final LwM2mTransportServiceImpl serviceImpl; - public LwM2mTransportRequest(LwM2mTransportContextServer context, LwM2mClientContext lwM2mClientContext, LeshanServer leshanServer, LwM2mTransportServiceImpl serviceImpl) { - this.context = context; + public LwM2mTransportRequest(LwM2mTransportContextServer lwM2mTransportContextServer, LwM2mClientContext lwM2mClientContext, LeshanServer leshanServer, LwM2mTransportServiceImpl serviceImpl) { + this.lwM2mTransportContextServer = lwM2mTransportContextServer; this.lwM2mClientContext = lwM2mClientContext; this.leshanServer = leshanServer; this.serviceImpl = serviceImpl; @@ -101,7 +101,7 @@ public class LwM2mTransportRequest { @PostConstruct public void init() { this.converter = LwM2mValueConverterImpl.getInstance(); - executorResponse = Executors.newFixedThreadPool(this.context.getLwM2MTransportConfigServer().getRequestPoolSize(), + executorResponse = Executors.newFixedThreadPool(this.lwM2mTransportContextServer.getLwM2MTransportConfigServer().getRequestPoolSize(), new NamedThreadFactory(String.format("LwM2M %s channel response", RESPONSE_CHANNEL))); } @@ -120,7 +120,8 @@ public class LwM2mTransportRequest { if (registration != null && resultIds.getObjectId() >= 0) { DownlinkRequest request = null; ContentFormat contentFormat = contentFormatParam != null ? ContentFormat.fromName(contentFormatParam.toUpperCase()) : null; - ResourceModel resource = serviceImpl.lwM2mTransportContextServer.getLwM2MTransportConfigServer().getResourceModel(registration, resultIds); + LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClientWithReg(registration, null); + ResourceModel resource = lwM2MClient.getResourceModel(target); timeoutInMs = timeoutInMs > 0 ? timeoutInMs : DEFAULT_TIMEOUT; switch (typeOper) { case GET_TYPE_OPER_READ: @@ -217,7 +218,10 @@ public class LwM2mTransportRequest { } if (request != null) { - this.sendRequest(registration, request, timeoutInMs); + this.sendRequest(registration, lwM2MClient, request, timeoutInMs); + } + else { + log.error("[{}], [{}] - [{}] error SendRequest", registration.getEndpoint(), typeOper, target); } } } @@ -230,8 +234,7 @@ public class LwM2mTransportRequest { */ @SuppressWarnings("unchecked") - private void sendRequest(Registration registration, DownlinkRequest request, long timeoutInMs) { - LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClientWithReg(registration, null); + private void sendRequest(Registration registration, LwM2mClient lwM2MClient, DownlinkRequest request, long timeoutInMs) { leshanServer.send(registration, request, timeoutInMs, (ResponseCallback) response -> { if (!lwM2MClient.isInit()) { lwM2MClient.initValue(this.serviceImpl, convertToIdVerFromObjectId(request.getPath().toString(), registration)); diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportService.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportService.java index 8d1aff37b5..fb917f1370 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportService.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportService.java @@ -47,6 +47,10 @@ public interface LwM2mTransportService { void onDeviceUpdate(TransportProtos.SessionInfoProto sessionInfo, Device device, Optional deviceProfileOpt); + void onResourceUpdate (Optional resourceUpdateMsgOpt); + + void onResourceDelete(Optional resourceDeleteMsgOpt); + void doTrigger(Registration registration, String path); void doDisconnect(TransportProtos.SessionInfoProto sessionInfo); 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 6fc9932f97..8d43b76446 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 @@ -52,7 +52,6 @@ import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient; import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext; import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientProfile; -import org.thingsboard.server.transport.lwm2m.server.client.ResourceValue; import org.thingsboard.server.transport.lwm2m.server.client.ResultsAnalyzerParameters; import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl; @@ -73,9 +72,6 @@ import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.stream.Collectors; import static org.thingsboard.server.common.transport.util.JsonUtils.getJsonObject; @@ -107,8 +103,6 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { private ExecutorService executorUpdateRegistered; private ExecutorService executorUnRegistered; private LwM2mValueConverterImpl converter; - protected final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); - protected final Lock writeLock = readWriteLock.writeLock(); private final TransportService transportService; @@ -162,7 +156,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { if (lwM2MClient != null) { SessionInfoProto sessionInfo = this.getValidateSessionInfo(registration); if (sessionInfo != null) { - this.initLwM2mClient (lwM2MClient, sessionInfo); + this.initLwM2mClient(lwM2MClient, sessionInfo); transportService.registerAsyncSession(sessionInfo, new LwM2mSessionMsgListener(this, sessionInfo)); transportService.process(sessionInfo, DefaultTransportService.getSessionEventMsg(SessionEvent.OPEN), null); transportService.process(sessionInfo, TransportProtos.SubscribeToAttributeUpdatesMsg.newBuilder().build(), null); @@ -223,7 +217,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { }); } - private void initLwM2mClient (LwM2mClient lwM2MClient, SessionInfoProto sessionInfo) { + private void initLwM2mClient(LwM2mClient lwM2MClient, SessionInfoProto sessionInfo) { lwM2MClient.setDeviceId(new UUID(sessionInfo.getDeviceIdMSB(), sessionInfo.getDeviceIdLSB())); lwM2MClient.setProfileId(new UUID(sessionInfo.getDeviceProfileIdMSB(), sessionInfo.getDeviceProfileIdLSB())); lwM2MClient.setDeviceName(sessionInfo.getDeviceName()); @@ -309,7 +303,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClient(new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB())); LwM2mClientProfile clientProfile = lwM2mClientContext.getProfile(new UUID(sessionInfo.getDeviceProfileIdMSB(), sessionInfo.getDeviceProfileIdLSB())); if (pathIdVer != null && !pathIdVer.isEmpty() && (this.validatePathInAttrProfile(clientProfile, pathIdVer) || this.validatePathInTelemetryProfile(clientProfile, pathIdVer))) { - ResourceModel resourceModel = lwM2mTransportContextServer.getLwM2MTransportConfigServer().getResourceModel(lwM2MClient.getRegistration(), new LwM2mPath(convertToObjectIdFromIdVer(pathIdVer))); + ResourceModel resourceModel = lwM2MClient.getResourceModel(pathIdVer); if (resourceModel != null && resourceModel.operations.isWritable()) { lwM2mTransportRequest.sendAllRequest(lwM2MClient.getRegistration(), pathIdVer, POST_TYPE_OPER_WRITE_REPLACE, ContentFormat.TLV.getName(), null, value, this.lwM2mTransportContextServer.getLwM2MTransportConfigServer().getTimeout()); @@ -360,6 +354,26 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { registrationIdOpt.ifPresent(registrationId -> this.onDeviceUpdateLwM2MClient(registrationId, device, deviceProfileOpt)); } + /** + * + * @param resourceUpdateMsgOpt - + */ + @Override + public void onResourceUpdate (Optional resourceUpdateMsgOpt) { + String idVer = resourceUpdateMsgOpt.get().getResourceKey(); // 19_1.0 + lwM2mClientContext.getLwM2mClients().values().stream().forEach(e -> e.updateResourceModel(idVer, this.lwM2mTransportContextServer.getLwM2MTransportConfigServer().getModelProvider())); + } + + /** + * + * @param resourceDeleteMsgOpt - + */ + @Override + public void onResourceDelete(Optional resourceDeleteMsgOpt) { + String pathIdVer = resourceDeleteMsgOpt.get().getResourceKey(); // 19_1.0 + lwM2mClientContext.getLwM2mClients().values().stream().forEach(e -> e.deleteResources(pathIdVer, this.lwM2mTransportContextServer.getLwM2MTransportConfigServer().getModelProvider())); + } + /** * Trigger Server path = "/1/0/8" *

@@ -519,10 +533,14 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { */ private void updateResourcesValue(Registration registration, LwM2mResource lwM2mResource, String path) { LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClientWithReg(registration, null); - lwM2MClient.updateResourceValue(path, lwM2mResource); - Set paths = new HashSet<>(); - paths.add(path); - this.updateAttrTelemetry(registration, paths); + if (lwM2MClient.saveResourceValue(path, lwM2mResource, this.lwM2mTransportContextServer.getLwM2MTransportConfigServer().getModelProvider())) { + Set paths = new HashSet<>(); + paths.add(path); + this.updateAttrTelemetry(registration, paths); + } + else { + log.error("Fail update Resource [{}]", lwM2mResource); + } } /** @@ -538,12 +556,9 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { JsonObject attributes = new JsonObject(); JsonObject telemetries = new JsonObject(); try { - writeLock.lock(); this.getParametersFromProfile(attributes, telemetries, registration, paths); } catch (Exception e) { log.error("UpdateAttrTelemetry", e); - } finally { - writeLock.unlock(); } if (attributes.getAsJsonObject().entrySet().size() > 0) this.updateParametersOnThingsboard(attributes, DEVICE_ATTRIBUTES_TOPIC, registration); @@ -558,8 +573,8 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { */ private boolean validatePathInAttrProfile(LwM2mClientProfile clientProfile, String path) { try { - List attributesSet = new Gson().fromJson(clientProfile.getPostAttributeProfile(), new TypeToken>() { - }.getType()); + List attributesSet = new Gson().fromJson(clientProfile.getPostAttributeProfile(), + new TypeToken>() {}.getType()); return attributesSet.stream().anyMatch(p -> p.equals(path)); } catch (Exception e) { log.error("Fail Validate Path [{}] ClientProfile.Attribute", path, e); @@ -717,9 +732,9 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { */ private String getResourceValueToString(LwM2mClient lwM2MClient, String path) { LwM2mPath pathIds = new LwM2mPath(convertToObjectIdFromIdVer(path)); - ResourceValue resourceValue = this.returnResourceValueFromLwM2MClient(lwM2MClient, path); + LwM2mResource resourceValue = this.returnResourceValueFromLwM2MClient(lwM2MClient, path); return resourceValue == null ? null : - this.converter.convertValue(resourceValue.getResourceValue(), this.lwM2mTransportContextServer.getLwM2MTransportConfigServer().getResourceModelType(lwM2MClient.getRegistration(), pathIds), ResourceModel.Type.STRING, pathIds).toString(); + this.converter.convertValue(resourceValue.isMultiInstances() ? resourceValue.getValues() : resourceValue.getValue(), resourceValue.getType(), ResourceModel.Type.STRING, pathIds).toString(); } /** @@ -727,10 +742,10 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { * @param path - * @return - return value of Resource by idPath */ - private ResourceValue returnResourceValueFromLwM2MClient(LwM2mClient lwM2MClient, String path) { - ResourceValue resourceValue = null; + private LwM2mResource returnResourceValueFromLwM2MClient(LwM2mClient lwM2MClient, String path) { + LwM2mResource resourceValue = null; if (new LwM2mPath(convertToObjectIdFromIdVer(path)).isResource()) { - resourceValue = lwM2MClient.getResources().get(path); + resourceValue = lwM2MClient.getResources().get(path).getLwM2mResource(); } return resourceValue; } @@ -967,9 +982,9 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { */ private String getPathAttributeUpdateProfile(TransportProtos.SessionInfoProto sessionInfo, String name) { LwM2mClientProfile profile = lwM2mClientContext.getProfile(new UUID(sessionInfo.getDeviceProfileIdMSB(), sessionInfo.getDeviceProfileIdLSB())); - Registration registration = lwM2mClientContext.getLwM2MClient(sessionInfo).getRegistration(); + LwM2mClient lwM2mClient = lwM2mClientContext.getLwM2MClient(sessionInfo); return profile.getPostKeyNameProfile().getAsJsonObject().entrySet().stream() - .filter(e -> e.getValue().getAsString().equals(name) && validateResourceInModel(registration, e.getKey(), false)).findFirst().map(Map.Entry::getKey) + .filter(e -> e.getValue().getAsString().equals(name) && validateResourceInModel(lwM2mClient, e.getKey(), false)).findFirst().map(Map.Entry::getKey) .orElse(""); } @@ -1118,7 +1133,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { ConcurrentMap keyNamesIsWritable = keyNamesMap.entrySet() .stream() - .filter(e -> (attrSet.contains(e.getKey()) && validateResourceInModel(lwM2MClient.getRegistration(), e.getKey(), true))) + .filter(e -> (attrSet.contains(e.getKey()) && validateResourceInModel(lwM2MClient, e.getKey(), true))) .collect(Collectors.toConcurrentMap(Map.Entry::getKey, Map.Entry::getValue)); Set namesIsWritable = ConcurrentHashMap.newKeySet(); @@ -1126,13 +1141,12 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { return new ArrayList<>(namesIsWritable); } - private boolean validateResourceInModel(Registration registration, String pathKey, boolean isWritable) { - ResourceModel resourceModel = lwM2mTransportContextServer.getLwM2MTransportConfigServer().getResourceModel(registration, - new LwM2mPath(convertToObjectIdFromIdVer(pathKey))); + private boolean validateResourceInModel(LwM2mClient lwM2mClient, String pathKey, boolean isWritable) { + ResourceModel resourceModel = lwM2mClient.getResourceModel(pathKey); Integer objectId = validateObjectIdFromKey(pathKey); String objectVer = validateObjectVerFromKey(pathKey); return resourceModel != null && (isWritable ? - objectId != null && objectVer != null && objectVer.equals(registration.getSupportedVersion(objectId)) && resourceModel.operations.isWritable() : - objectId != null && objectVer != null && objectVer.equals(registration.getSupportedVersion(objectId))); + objectId != null && objectVer != null && objectVer.equals(lwM2mClient.getRegistration().getSupportedVersion(objectId)) && resourceModel.operations.isWritable() : + objectId != null && objectVer != null && objectVer.equals(lwM2mClient.getRegistration().getSupportedVersion(objectId))); } } 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 fc35668fef..3705547325 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 @@ -85,7 +85,7 @@ public class LwM2mVersionedModelProvider implements LwM2mModelProvider { if (objectModel != null) return objectModel.resources.get(resourceId); else - log.warn("TbResources (Object model) with id [{}/{}] not found on the server", objectId, resourceId); + log.warn("TbResources (Object model) with id [{}/0/{}] not found on the server", objectId, resourceId); return null; } catch (Exception e) { log.error("", e); diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClient.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClient.java index 1c9afaab6d..bdb783e3ff 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClient.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClient.java @@ -17,9 +17,10 @@ package org.thingsboard.server.transport.lwm2m.server.client; import lombok.Data; import lombok.extern.slf4j.Slf4j; -import org.eclipse.leshan.core.node.LwM2mMultipleResource; +import org.eclipse.leshan.core.model.ResourceModel; +import org.eclipse.leshan.core.node.LwM2mPath; import org.eclipse.leshan.core.node.LwM2mResource; -import org.eclipse.leshan.core.node.LwM2mSingleResource; +import org.eclipse.leshan.server.model.LwM2mModelProvider; import org.eclipse.leshan.server.registration.Registration; import org.eclipse.leshan.server.security.SecurityInfo; import org.thingsboard.server.gen.transport.TransportProtos; @@ -28,9 +29,14 @@ import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportServiceImpl; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; +import java.util.stream.Collectors; + +import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_PATH; +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.convertToObjectIdFromIdVer; @Slf4j @Data @@ -67,21 +73,79 @@ public class LwM2mClient implements Cloneable { this.init = false; } - public void updateResourceValue(String pathRez, LwM2mResource rez) { - if (rez instanceof LwM2mMultipleResource) { - this.resources.put(pathRez, new ResourceValue(rez.getValues(), null, true)); - } else if (rez instanceof LwM2mSingleResource) { - this.resources.put(pathRez, new ResourceValue(null, rez.getValue(), false)); + public boolean saveResourceValue(String pathRez, LwM2mResource rez, LwM2mModelProvider modelProvider) { + if (this.resources.get(pathRez) != null && this.resources.get(pathRez).getResourceModel() != null) { + this.resources.get(pathRez).setLwM2mResource(rez); + return true; + } else { + LwM2mPath pathIds = new LwM2mPath(convertToObjectIdFromIdVer(pathRez)); + ResourceModel resourceModel = modelProvider.getObjectModel(registration).getResourceModel(pathIds.getObjectId(), pathIds.getResourceId()); + if (resourceModel != null) { + this.resources.put(pathRez, new ResourceValue(rez, resourceModel)); + return true; + } else { + return false; + } } } - public void initValue(LwM2mTransportServiceImpl lwM2MTransportService, String path) { + public ResourceModel getResourceModel(String pathRez) { + if (this.getResources().get(pathRez) != null) { + return this.getResources().get(pathRez).getResourceModel(); + } else { + return null; + } + } + + /** + * + * @param pathIdVer == "3_1.0" + * @param modelProvider - + */ + public void deleteResources(String pathIdVer, LwM2mModelProvider modelProvider) { + Set key = getKeysEqualsIdVer(pathIdVer); + key.forEach(pathRez -> { + LwM2mPath pathIds = new LwM2mPath(convertToObjectIdFromIdVer(pathRez.toString())); + ResourceModel resourceModel = modelProvider.getObjectModel(registration).getResourceModel(pathIds.getObjectId(), pathIds.getResourceId()); + if (resourceModel != null) { + this.resources.get(pathRez).setResourceModel(resourceModel); + } + else { + this.resources.remove(pathRez); + } + }); + } + + /** + * + * @param idVer - + * @param modelProvider - + */ + public void updateResourceModel(String idVer, LwM2mModelProvider modelProvider) { + Set key = getKeysEqualsIdVer(idVer); + key.forEach(k -> this.saveResourceModel(k.toString(), modelProvider)); + } + + private void saveResourceModel(String pathRez, LwM2mModelProvider modelProvider) { + LwM2mPath pathIds = new LwM2mPath(convertToObjectIdFromIdVer(pathRez)); + ResourceModel resourceModel = modelProvider.getObjectModel(registration).getResourceModel(pathIds.getObjectId(), pathIds.getResourceId()); + this.resources.get(pathRez).setResourceModel(resourceModel); + } + + private Set getKeysEqualsIdVer(String idVer) { + return this.resources.keySet() + .stream() + .filter(e -> idVer.equals(e.split(LWM2M_SEPARATOR_PATH)[1])) + .collect(Collectors.toSet()); + } + + public void initValue(LwM2mTransportServiceImpl serviceImpl, String path) { if (path != null) { this.pendingRequests.remove(path); } if (this.pendingRequests.size() == 0) { this.init = true; - lwM2MTransportService.putDelayedUpdateResourcesThingsboard(this); + serviceImpl.putDelayedUpdateResourcesThingsboard(this); } } 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 8285c9bc8b..1c4042bd1a 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 @@ -34,25 +34,25 @@ public class LwM2mClientProfile { /** * {"keyName": { - * "/3/0/1": "modelNumber", - * "/3/0/0": "manufacturer", - * "/3/0/2": "serialNumber" + * "/3_1.0/0/1": "modelNumber", + * "/3_1.0/0/0": "manufacturer", + * "/3_1.0/0/2": "serialNumber" * } **/ private JsonObject postKeyNameProfile; /** - * [ "/2/0/0", "/2/0/1"] + * [ "/3_1.0/0/0", "/3_1.0/0/1"] */ private JsonArray postAttributeProfile; /** - * [ "/2/0/0", "/2/0/1"] + * [ "/3_1.0/0/0", "/3_1.0/0/2"] */ private JsonArray postTelemetryProfile; /** - * [ "/2/0/0", "/2/0/1"] + * [ "/3_1.0/0", "/3_1.0/0/1, "/3_1.0/0/2"] */ private JsonArray postObserveProfile; diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/ResourceValue.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/ResourceValue.java index 3ff04f288b..cbaf60ca77 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/ResourceValue.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/ResourceValue.java @@ -16,23 +16,16 @@ package org.thingsboard.server.transport.lwm2m.server.client; import lombok.Data; - -import java.util.Map; +import org.eclipse.leshan.core.model.ResourceModel; +import org.eclipse.leshan.core.node.LwM2mResource; @Data public class ResourceValue { - Map values; - Object value; - boolean multiInstances; + private LwM2mResource lwM2mResource; + private ResourceModel resourceModel; - public ResourceValue(Map values, Object value, boolean multiInstances) { - this.values = values; - this.value = value; - this.multiInstances = multiInstances; + public ResourceValue(LwM2mResource lwM2mResource, ResourceModel resourceModel) { + this.lwM2mResource = lwM2mResource; + this.resourceModel = resourceModel; } - - public Object getResourceValue() { - return this.multiInstances ? this.values : this.value; - } - } diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/SessionMsgListener.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/SessionMsgListener.java index 8209fe2531..51a953e4b2 100644 --- a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/SessionMsgListener.java +++ b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/SessionMsgListener.java @@ -18,11 +18,11 @@ package org.thingsboard.server.common.transport; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.DeviceProfile; import org.thingsboard.server.gen.transport.TransportProtos; -import org.thingsboard.server.gen.transport.TransportProtos.ToServerRpcResponseMsg; import org.thingsboard.server.gen.transport.TransportProtos.AttributeUpdateNotificationMsg; import org.thingsboard.server.gen.transport.TransportProtos.GetAttributeResponseMsg; import org.thingsboard.server.gen.transport.TransportProtos.SessionCloseNotificationProto; import org.thingsboard.server.gen.transport.TransportProtos.ToDeviceRpcRequestMsg; +import org.thingsboard.server.gen.transport.TransportProtos.ToServerRpcResponseMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToTransportUpdateCredentialsProto; import java.util.Optional; @@ -44,9 +44,12 @@ public interface SessionMsgListener { default void onToTransportUpdateCredentials(ToTransportUpdateCredentialsProto toTransportUpdateCredentials){} - default void onDeviceProfileUpdate(TransportProtos.SessionInfoProto newSessionInfo, DeviceProfile deviceProfile) { - } + default void onDeviceProfileUpdate(TransportProtos.SessionInfoProto newSessionInfo, DeviceProfile deviceProfile) {} - default void onDeviceUpdate(TransportProtos.SessionInfoProto sessionInfo, Device device, Optional deviceProfileOpt) { - } + default void onDeviceUpdate(TransportProtos.SessionInfoProto sessionInfo, Device device, + Optional deviceProfileOpt) {} + + default void onResourceUpdate(Optional resourceUpdateMsgOpt) {} + + default void onResourceDelete(Optional resourceUpdateMsgOpt) {} } 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 ebd439b12b..1947e6cada 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,7 @@ package org.thingsboard.server.common.transport.lwm2m; import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; -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; import org.springframework.stereotype.Component; @@ -219,13 +216,4 @@ public class LwM2MTransportConfigServer { } return FULL_FILE_PATH.toUri().getPath(); } - - public ResourceModel getResourceModel(Registration registration, LwM2mPath pathIds) { - return this.modelProvider.getObjectModel(registration).getResourceModel(pathIds.getObjectId(), pathIds.getResourceId()); - } - - public ResourceModel.Type getResourceModelType(Registration registration, LwM2mPath pathIds) { - ResourceModel resource = this.getResourceModel(registration, pathIds); - return (resource == null) ? null : resource.type; - } } 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 5882790684..740a2a622f 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 @@ -288,7 +288,7 @@ public class DefaultTransportService implements TransportService { } @Override - public void process(TransportProtos.ValidateDeviceLwM2MCredentialsRequestMsg msg, TransportServiceCallback callback) { + public void process(TransportProtos.ValidateDeviceLwM2MCredentialsRequestMsg msg, TransportServiceCallback callback) { log.trace("Processing msg: {}", msg); TbProtoQueueMsg protoMsg = new TbProtoQueueMsg<>(UUID.randomUUID(), TransportApiRequestMsg.newBuilder().setValidateDeviceLwM2MCredentialsRequestMsg(msg).build()); AsyncCallbackTemplate.withCallback(transportApiRequestTemplate.send(protoMsg), @@ -710,12 +710,21 @@ public class DefaultTransportService implements TransportService { ResourceType resourceType = ResourceType.valueOf(msg.getResourceType()); String resourceId = msg.getResourceKey(); transportResourceCache.update(tenantId, resourceType, resourceId); + sessions.forEach((id, mdRez) -> { + log.warn("ResourceUpdate - [{}] [{}]", id, mdRez); + transportCallbackExecutor.submit(() -> mdRez.getListener().onResourceUpdate(Optional.ofNullable(msg))); + }); + } else if (toSessionMsg.hasResourceDeleteMsg()) { TransportProtos.ResourceDeleteMsg msg = toSessionMsg.getResourceDeleteMsg(); TenantId tenantId = new TenantId(new UUID(msg.getTenantIdMSB(), msg.getTenantIdLSB())); ResourceType resourceType = ResourceType.valueOf(msg.getResourceType()); String resourceId = msg.getResourceKey(); transportResourceCache.evict(tenantId, resourceType, resourceId); + sessions.forEach((id, mdRez) -> { + log.warn("ResourceDelete - [{}] [{}]", id, mdRez); + transportCallbackExecutor.submit(() -> mdRez.getListener().onResourceDelete(Optional.ofNullable(msg))); + }); } else { //TODO: should we notify the device actor about missed session? log.debug("[{}] Missing session.", sessionId); @@ -827,7 +836,7 @@ public class DefaultTransportService implements TransportService { } private void sendToRuleEngine(TenantId tenantId, DeviceId deviceId, TransportProtos.SessionInfoProto sessionInfo, JsonObject json, - TbMsgMetaData metaData, SessionMsgType sessionMsgType, TbQueueCallback callback) { + TbMsgMetaData metaData, SessionMsgType sessionMsgType, TbQueueCallback callback) { DeviceProfileId deviceProfileId = new DeviceProfileId(new UUID(sessionInfo.getDeviceProfileIdMSB(), sessionInfo.getDeviceProfileIdLSB())); DeviceProfile deviceProfile = deviceProfileCache.get(deviceProfileId); RuleChainId ruleChainId; diff --git a/dao/src/main/java/org/thingsboard/server/dao/resource/BaseTbResourceService.java b/dao/src/main/java/org/thingsboard/server/dao/resource/BaseTbResourceService.java index 0f1b39a459..0df2f19e80 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/resource/BaseTbResourceService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/resource/BaseTbResourceService.java @@ -31,7 +31,7 @@ import org.thingsboard.server.common.data.id.TbResourceId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.lwm2m.LwM2mInstance; import org.thingsboard.server.common.data.lwm2m.LwM2mObject; -import org.thingsboard.server.common.data.lwm2m.LwM2mResource; +import org.thingsboard.server.common.data.lwm2m.LwM2mResourceObserve; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.dao.exception.DataValidationException; @@ -87,7 +87,9 @@ public class BaseTbResourceService implements TbResourceService { String resourceKey = objectModel.id + LWM2M_SEPARATOR_KEY + objectModel.getVersion(); String name = objectModel.name; resource.setResourceKey(resourceKey); - resource.setTitle(name + " id=" +objectModel.id + " v" + objectModel.getVersion()); + if (resource.getId() == null) { + resource.setTitle(name + " id=" + objectModel.id + " v" + objectModel.getVersion()); + } resource.setSearchText(resourceKey + LWM2M_SEPARATOR_SEARCH_TEXT + name); } else { throw new DataValidationException(String.format("Could not parse the XML of objectModel with name %s", resource.getSearchText())); @@ -205,14 +207,14 @@ public class BaseTbResourceService implements TbResourceService { lwM2mObject.setMandatory(obj.mandatory); LwM2mInstance instance = new LwM2mInstance(); instance.setId(0); - List resources = new ArrayList<>(); + List resources = new ArrayList<>(); obj.resources.forEach((k, v) -> { if (!v.operations.isExecutable()) { - LwM2mResource lwM2mResource = new LwM2mResource(k, v.name, false, false, false); - resources.add(lwM2mResource); + LwM2mResourceObserve lwM2MResourceObserve = new LwM2mResourceObserve(k, v.name, false, false, false); + resources.add(lwM2MResourceObserve); } }); - instance.setResources(resources.toArray(LwM2mResource[]::new)); + instance.setResources(resources.toArray(LwM2mResourceObserve[]::new)); lwM2mObject.setInstances(new LwM2mInstance[]{instance}); return lwM2mObject; }