diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2MTransportMsgHandler.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2MTransportMsgHandler.java index 8e059e5a3b..5d724b940b 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2MTransportMsgHandler.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2MTransportMsgHandler.java @@ -33,7 +33,6 @@ import org.eclipse.leshan.core.request.ContentFormat; import org.eclipse.leshan.core.request.WriteRequest; import org.eclipse.leshan.core.response.ReadResponse; import org.eclipse.leshan.core.util.NamedThreadFactory; -import org.eclipse.leshan.server.californium.LeshanServer; import org.eclipse.leshan.server.registration.Registration; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; @@ -102,7 +101,6 @@ import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandle import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil.LwM2mTypeOper.READ; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil.LwM2mTypeOper.WRITE_ATTRIBUTES; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil.LwM2mTypeOper.WRITE_REPLACE; -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil.LwM2mTypeOper.WRITE_UPDATE; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil.SERVICE_CHANNEL; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil.convertJsonArrayToSet; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandlerUtil.convertPathFromIdVerToObjectId; @@ -490,15 +488,17 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler if (OBSERVE_READ_ALL != lwm2mClientRpcRequest.getTypeOper() && lwm2mClientRpcRequest.getTargetIdVer() == null) { lwm2mClientRpcRequest.setErrorMsg(lwm2mClientRpcRequest.targetIdVerKey + " and " + lwm2mClientRpcRequest.keyNameKey + " is null or bad format"); - } else if ((EXECUTE == lwm2mClientRpcRequest.getTypeOper() + } + /** + * EXECUTE && WRITE_REPLACE - only for Resource or ResourceInstance + */ + else if ((EXECUTE == lwm2mClientRpcRequest.getTypeOper() || WRITE_REPLACE == lwm2mClientRpcRequest.getTypeOper()) && lwm2mClientRpcRequest.getTargetIdVer() != null && !(new LwM2mPath(convertPathFromIdVerToObjectId(lwm2mClientRpcRequest.getTargetIdVer())).isResource() || new LwM2mPath(convertPathFromIdVerToObjectId(lwm2mClientRpcRequest.getTargetIdVer())).isResourceInstance())) { lwm2mClientRpcRequest.setErrorMsg("Invalid parameter " + lwm2mClientRpcRequest.targetIdVerKey + ". Only Resource or ResourceInstance can be this operation"); - } else if (WRITE_UPDATE == lwm2mClientRpcRequest.getTypeOper()) { - lwm2mClientRpcRequest.setErrorMsg("Procedures In Development..."); } } else { lwm2mClientRpcRequest.setErrorMsg("Params of request is bad Json format."); @@ -930,7 +930,15 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler * @param request - */ public void onWriteResponseOk(Registration registration, String path, WriteRequest request) { - this.updateResourcesValue(registration, ((LwM2mResource) request.getNode()), path); + if (request.getNode() instanceof LwM2mResource) { + this.updateResourcesValue(registration, ((LwM2mResource) request.getNode()), path); + } + else if (request.getNode() instanceof LwM2mObjectInstance) { + ((LwM2mObjectInstance) request.getNode()).getResources().forEach((resId, resource) -> { + this.updateResourcesValue(registration, resource, path+ "/" + resId); + }); + } + } /** 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 3557af6d40..e38823240b 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 @@ -16,13 +16,13 @@ package org.thingsboard.server.transport.lwm2m.server; import lombok.RequiredArgsConstructor; -import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.eclipse.californium.core.coap.CoAP; import org.eclipse.californium.core.coap.Response; import org.eclipse.leshan.core.model.ResourceModel; import org.eclipse.leshan.core.node.LwM2mNode; 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.core.node.ObjectLink; import org.eclipse.leshan.core.observation.Observation; @@ -46,10 +46,8 @@ import org.eclipse.leshan.core.response.WriteAttributesResponse; import org.eclipse.leshan.core.response.WriteResponse; 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.stereotype.Service; -import org.thingsboard.server.common.transport.TransportService; import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig; import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient; @@ -59,6 +57,7 @@ import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl; import javax.annotation.PostConstruct; import java.util.Arrays; +import java.util.Collection; import java.util.Date; import java.util.Set; import java.util.concurrent.ExecutorService; @@ -111,7 +110,7 @@ public class LwM2mTransportRequest { * @param typeOper - * @param contentFormatName - */ - @SneakyThrows + public void sendAllRequest(Registration registration, String targetIdVer, LwM2mTypeOper typeOper, String contentFormatName, Object params, long timeoutInMs, Lwm2mClientRpcRequest rpcRequest) { try { @@ -160,8 +159,7 @@ public class LwM2mTransportRequest { break; case WRITE_REPLACE: // Request to write a String Single-Instance Resource using the TLV content format. - resourceModel = lwM2MClient.getResourceModel(targetIdVer, this.config - .getModelProvider()); + resourceModel = lwM2MClient.getResourceModel(targetIdVer, this.config.getModelProvider()); if (contentFormat.equals(ContentFormat.TLV)) { request = this.getWriteRequestSingleResource(null, resultIds.getObjectId(), resultIds.getObjectInstanceId(), resultIds.getResourceId(), params, resourceModel.type, @@ -175,15 +173,31 @@ public class LwM2mTransportRequest { } break; case WRITE_UPDATE: -// LwM2mNode node = null; -// if (resultIds.isObjectInstance()) { -// node = new LwM2mObjectInstance(resultIds.getObjectInstanceId(), lwM2MClient. -// getNewResourcesForInstance(targetIdVer, this.lwM2mTransportContextServer.getLwM2MTransportConfigServer().getModelProvider(), -// this.converter)); -// request = new WriteRequest(WriteRequest.Mode.UPDATE, contentFormat, target, node); -// } else if (resultIds.getObjectId() >= 0) { -// request = new ObserveRequest(resultIds.getObjectId()); -// } + if (resultIds.isResource()) { + /** + * send request: path = '/3/0' node == wM2mObjectInstance + * with params == "\"resources\": {15: resource:{id:15. value:'+01'...}} + **/ + Collection resources = lwM2MClient.getNewResourcesForInstance( + targetIdVer, params, + this.config.getModelProvider(), + this.converter); + request = new WriteRequest(WriteRequest.Mode.UPDATE, contentFormat, resultIds.getObjectId(), + resultIds.getObjectInstanceId(), resources); + } + + /** + * params = "{\"id\":0,\"resources\":[{\"id\":14,\"value\":\"+5\"},{\"id\":15,\"value\":\"+9\"}]}" + * + * int rscId = resultIds.getObjectInstanceId(); + */ + + else if (resultIds.isObjectInstance()) { + String content = (String) params; +// node = Gson.fromJson((content, LwM2mNode.class); + } else if (resultIds.getObjectId() >= 0) { + request = new ObserveRequest(resultIds.getObjectId()); + } break; case WRITE_ATTRIBUTES: request = createWriteAttributeRequest(target, params); @@ -236,7 +250,11 @@ public class LwM2mTransportRequest { String msg = String.format("%s: type operation %s %s", LOG_LW2M_ERROR, typeOper.name(), e.getMessage()); serviceImpl.sendLogsToThingsboard(msg, registration.getId()); - throw new Exception(e); + try { + throw new Exception(e); + } catch (Exception exception) { + exception.printStackTrace(); + } } } @@ -248,6 +266,7 @@ public class LwM2mTransportRequest { @SuppressWarnings("unchecked") private void sendRequest(Registration registration, LwM2mClient lwM2MClient, DownlinkRequest request, long timeoutInMs, Lwm2mClientRpcRequest rpcRequest) { + context.getServer().send(registration, request, timeoutInMs, (ResponseCallback) response -> { if (!lwM2MClient.isInit()) { lwM2MClient.initReadValue(this.serviceImpl, convertPathFromObjectIdToIdVer(request.getPath().toString(), 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 index bb27b66d69..654f96145a 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 @@ -117,9 +117,7 @@ public class LwM2mVersionedModelProvider implements LwM2mModelProvider { private ObjectModel getObjectModelDynamic(Integer objectId, String version) { String key = getKeyIdVer(objectId, version); - Optional tbResource = context.getTransportResourceCache().get(this.tenantId, LWM2M_MODEL, key); - return tbResource.map(resource -> helper.parseFromXmlToObjectModel( Base64.getDecoder().decode(resource.getData()), key + ".xml", 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 df212790da..3e56cbb374 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 @@ -26,8 +26,8 @@ import org.eclipse.leshan.server.registration.Registration; import org.eclipse.leshan.server.security.SecurityInfo; import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceCredentialsResponseMsg; -import org.thingsboard.server.transport.lwm2m.server.LwM2mQueuedRequest; import org.thingsboard.server.transport.lwm2m.server.DefaultLwM2MTransportMsgHandler; +import org.thingsboard.server.transport.lwm2m.server.LwM2mQueuedRequest; import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl; import java.util.Collection; @@ -111,15 +111,17 @@ public class LwM2mClient implements Cloneable { .getResourceModel(pathIds.getObjectId(), pathIds.getResourceId()) : null; } - public Collection getNewResourcesForInstance(String pathRezIdVer, LwM2mModelProvider modelProvider, + public Collection getNewResourcesForInstance(String pathRezIdVer, Object params, LwM2mModelProvider modelProvider, LwM2mValueConverterImpl converter) { LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(pathRezIdVer)); Collection resources = ConcurrentHashMap.newKeySet(); Map resourceModels = modelProvider.getObjectModel(registration) .getObjectModel(pathIds.getObjectId()).resources; - resourceModels.forEach((k, resourceModel) -> { - resources.add(LwM2mSingleResource.newResource(k, converter.convertValue("0", ResourceModel.Type.STRING, resourceModel.type, pathIds), resourceModel.type)); - }); + resourceModels.forEach((resId, resourceModel) -> { + if (resId == pathIds.getResourceId()) { + resources.add(LwM2mSingleResource.newResource(resId, converter.convertValue(params, ResourceModel.Type.STRING, resourceModel.type, pathIds), resourceModel.type)); + + }}); return resources; } 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 dce34c9cf6..3395fd7090 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 @@ -60,11 +60,14 @@ public class LwM2mValueConverterImpl implements LwM2mValueConverter { case INTEGER: switch (currentType) { case FLOAT: - log.debug("Trying to convert float value [{}] to integer", value); + log.debug("Trying to convert float value [{}] to Integer", value); Long longValue = ((Double) value).longValue(); if ((double) value == longValue.doubleValue()) { return longValue; } + case STRING: + log.debug("Trying to convert String value [{}] to Integer", value); + return Long.parseLong((String) value); default: break; } @@ -77,6 +80,9 @@ public class LwM2mValueConverterImpl implements LwM2mValueConverter { if ((long) value == floatValue.longValue()) { return floatValue; } + case STRING: + log.debug("Trying to convert String value [{}] to Float", value); + return Float.valueOf((String) value); default: break; }