callback) {
+ validateVersionedId(client, request);
int observeCancelCnt = context.getServer().getObservationService().cancelObservations(client.getRegistration(), request.getObjectId());
callback.onSuccess(request, observeCancelCnt);
}
@@ -214,51 +254,92 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im
sendSimpleRequest(client, new DiscoverRequest(request.getObjectId()), request.getTimeout(), callback);
}
+ /**
+ * Example # 1:
+ * AttributeSet attributes = new AttributeSet(new Attribute(Attribute.MINIMUM_PERIOD, 10L),
+ * new Attribute(Attribute.MAXIMUM_PERIOD, 100L));
+ * WriteAttributesRequest requestTest = new WriteAttributesRequest(3, 0, 14, attributes);
+ * sendSimpleRequest(client, requestTest, request.getTimeout(), callback);
+ *
+ * Example # 2
+ * Dimension and Object version are read only attributes.
+ * addAttribute(attributes, DIMENSION, params.getDim(), dim -> dim >= 0 && dim <= 255);
+ * addAttribute(attributes, OBJECT_VERSION, params.getVer(), StringUtils::isNotEmpty, Function.identity());
+ */
@Override
public void sendWriteAttributesRequest(LwM2mClient client, TbLwM2MWriteAttributesRequest request, DownlinkRequestCallback callback) {
- validateVersionedId(client, request);
- if (request.getAttributes() == null) {
- throw new IllegalArgumentException("Attributes to write are not specified!");
+ try {
+ validateVersionedId(client, request);
+ if (request.getAttributes() == null) {
+ throw new IllegalArgumentException("Attributes to write are not specified!");
+ }
+ ObjectAttributes params = request.getAttributes();
+ List attributes = new LinkedList<>();
+ addAttribute(attributes, MAXIMUM_PERIOD, params.getPmax());
+ addAttribute(attributes, MINIMUM_PERIOD, params.getPmin());
+ addAttribute(attributes, GREATER_THAN, params.getGt());
+ addAttribute(attributes, LESSER_THAN, params.getLt());
+ addAttribute(attributes, STEP, params.getSt());
+ AttributeSet attributeSet = new AttributeSet(attributes);
+ sendSimpleRequest(client, new WriteAttributesRequest(request.getObjectId(), attributeSet), request.getTimeout(), callback);
+ } catch (InvalidRequestException e) {
+ callback.onValidationError(request.toString(), e.getMessage());
}
- ObjectAttributes params = request.getAttributes();
- List attributes = new LinkedList<>();
-// Dimension and Object version are read only attributes.
-// addAttribute(attributes, DIMENSION, params.getDim(), dim -> dim >= 0 && dim <= 255);
-// addAttribute(attributes, OBJECT_VERSION, params.getVer(), StringUtils::isNotEmpty, Function.identity());
- addAttribute(attributes, MAXIMUM_PERIOD, params.getPmax());
- addAttribute(attributes, MINIMUM_PERIOD, params.getPmin());
- addAttribute(attributes, GREATER_THAN, params.getGt());
- addAttribute(attributes, LESSER_THAN, params.getLt());
- addAttribute(attributes, STEP, params.getSt());
- AttributeSet attributeSet = new AttributeSet(attributes);
- sendSimpleRequest(client, new WriteAttributesRequest(request.getObjectId(), attributeSet), request.getTimeout(), callback);
}
@Override
public void sendWriteReplaceRequest(LwM2mClient client, TbLwM2MWriteReplaceRequest request, DownlinkRequestCallback callback) {
- ResourceModel resourceModelWrite = client.getResourceModel(request.getVersionedId(), modelProvider);
- if (resourceModelWrite != null) {
- ContentFormat contentFormat = convertResourceModelTypeToContentFormat(client, resourceModelWrite.type);
- try {
- LwM2mPath path = new LwM2mPath(request.getObjectId());
- WriteRequest downlink = this.getWriteRequestSingleResource(resourceModelWrite.type, contentFormat,
- path.getObjectId(), path.getObjectInstanceId(), path.getResourceId(), request.getValue());
- sendSimpleRequest(client, downlink, request.getTimeout(), callback);
- } catch (Exception e) {
- callback.onError(toString(request), e);
+ LwM2mPath resultIds = new LwM2mPath(request.getObjectId());
+ if (resultIds.isResource() || resultIds.isResourceInstance()) {
+ validateVersionedId(client, request);
+ ResourceModel resourceModelWrite = client.getResourceModel(request.getVersionedId(), modelProvider);
+ if (resourceModelWrite != null) {
+ ContentFormat contentFormat = getWriteRequestContentFormat(client, request, modelProvider);
+ try {
+ WriteRequest downlink = null;
+ String msgError = "";
+ if (resourceModelWrite.multiple) {
+ try {
+ Map value = convertMultiResourceValuesFromRpcBody(request.getValue(), resourceModelWrite.type, request.getObjectId());
+ downlink = new WriteRequest(contentFormat, resultIds.getObjectId(), resultIds.getObjectInstanceId(), resultIds.getResourceId(),
+ value, resourceModelWrite.type);
+ } catch (Exception e) {
+ }
+ }
+ if (downlink == null) {
+ try {
+ downlink = this.getWriteRequestSingleResource(resourceModelWrite.type, contentFormat,
+ resultIds.getObjectId(), resultIds.getObjectInstanceId(), resultIds.getResourceId(), request.getValue());
+ } catch (Exception e) {
+ msgError = "Resource id=" + resultIds.toString() + ", value = " + request.getValue() +
+ ", class = " + request.getValue().getClass().getSimpleName() + ". Format value is bad. Value for this Single Resource must be " + resourceModelWrite.type + "!";
+ }
+ }
+ if (downlink != null) {
+ sendSimpleRequest(client, downlink, request.getTimeout(), callback);
+ } else {
+ callback.onValidationError(toString(request), msgError);
+ }
+ } catch (Exception e) {
+ callback.onError(toString(request), e);
+ }
+ } else {
+ callback.onValidationError(toString(request), "Resource " + request.getVersionedId() + " is not configured in the device profile!");
}
} else {
- callback.onValidationError(toString(request), "Tenant hasn't such the TbResources: " + request.getVersionedId() + "!");
+ callback.onValidationError(toString(request), "Resource " + request.getVersionedId() + ". This operation can only be used for Resource or ResourceInstance!");
}
}
@Override
- public void sendWriteCompositeRequest(LwM2mClient client, RpcWriteCompositeRequest rpcWriteCompositeRequest, DownlinkRequestCallback callback) {
- ContentFormat contentFormat = ContentFormat.SENML_JSON;
+ public void sendWriteCompositeRequest(LwM2mClient client, RpcWriteCompositeRequest rpcWriteCompositeRequest,
+ DownlinkRequestCallback callback, ContentFormat contentFormatComposite) {
try {
- WriteCompositeRequest downlink = new WriteCompositeRequest(contentFormat, rpcWriteCompositeRequest.getNodes());
+ WriteCompositeRequest downlink = new WriteCompositeRequest(contentFormatComposite, rpcWriteCompositeRequest.getNodes());
//TODO: replace config.getTimeout();
- sendWriteCompositeRequest(client, downlink, config.getTimeout(), callback);
+ sendWriteCompositeRequest(client, downlink, this.config.getTimeout(), callback);
+ } catch (InvalidRequestException e) {
+ callback.onValidationError(rpcWriteCompositeRequest.toString(), e.getMessage());
} catch (Exception e) {
callback.onError(toString(rpcWriteCompositeRequest), e);
}
@@ -266,43 +347,111 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im
@Override
public void sendWriteUpdateRequest(LwM2mClient client, TbLwM2MWriteUpdateRequest request, DownlinkRequestCallback callback) {
- LwM2mPath resultIds = new LwM2mPath(request.getObjectId());
- if (resultIds.isResource()) {
- /*
- * send request: path = '/3/0' node == wM2mObjectInstance
- * with params == "\"resources\": {15: resource:{id:15. value:'+01'...}}
- **/
- Collection resources = client.getNewResourceForInstance(request.getVersionedId(), request.getValue(), modelProvider, this.converter);
- ResourceModel resourceModelWrite = client.getResourceModel(request.getVersionedId(), modelProvider);
- if (resourceModelWrite != null) {
- ContentFormat contentFormat = request.getObjectContentFormat() != null ? request.getObjectContentFormat() : convertResourceModelTypeToContentFormat(client, resourceModelWrite.type);
- WriteRequest downlink = new WriteRequest(WriteRequest.Mode.UPDATE, contentFormat, resultIds.getObjectId(),
- resultIds.getObjectInstanceId(), resources);
- sendSimpleRequest(client, downlink, request.getTimeout(), callback);
- }
- else {
- callback.onValidationError(toString(request), "Tenant hasn't such the TbResources: " + request.getVersionedId() + " !");
+ try {
+ LwM2mPath resultIds = new LwM2mPath(request.getObjectId());
+ if (resultIds.isObjectInstance() || resultIds.isResource()) {
+ validateVersionedId(client, request);
+ WriteRequest downlink = null;
+ ContentFormat contentFormat = getWriteRequestContentFormat(client, request, modelProvider);
+ String msgError = "";
+ if (resultIds.isObjectInstance()) {
+ /*
+ * params = "{\"id\":0,\"value\":[{\"id\":14,\"value\":\"+5\"},{\"id\":15,\"value\":\"+9\"}]}"
+ * int rscId = resultIds.getObjectInstanceId();
+ * contentFormat – Format of the payload (TLV or JSON).
+ */
+ Collection resources = client.getNewResourcesForInstance(request.getVersionedId(),
+ request.getValue(), modelProvider, this.converter);
+ if (resources.size() > 0) {
+ downlink = new WriteRequest(WriteRequest.Mode.UPDATE, contentFormat, resultIds.getObjectId(),
+ resultIds.getObjectInstanceId(), resources);
+ } else {
+ msgError = " No resources to update!";
+ }
+ } else if (resultIds.isResource()) {
+ ResourceModel resourceModelWrite = client.getResourceModel(request.getVersionedId(), modelProvider);
+ if (resourceModelWrite != null) {
+ if (resourceModelWrite.multiple) {
+ try {
+ Map value = convertMultiResourceValuesFromRpcBody(request.getValue(), resourceModelWrite.type, request.getObjectId());
+ downlink = new WriteRequest(WriteRequest.Mode.UPDATE, contentFormat, resultIds.getObjectId(),
+ resultIds.getObjectInstanceId(), resultIds.getResourceId(),
+ value, resourceModelWrite.type);
+ } catch (Exception e1) {
+ msgError = " Resource id=" + resultIds.toString() +
+ ", class = " + request.getValue().getClass().getSimpleName() +
+ ", value = " + request.getValue() + " is bad. " +
+ "Value of Multi-Instance Resource must be in Json format!";
+ }
+ }
+ } else {
+ msgError = " Resource " + request.getVersionedId() + " is not configured in the device profile!";
+ }
+ }
+ if (downlink != null) {
+ sendSimpleRequest(client, downlink, request.getTimeout(), callback);
+ } else {
+ callback.onValidationError(toString(request), "Resource " + request.getVersionedId() +
+ ". This operation can only be used for ObjectInstance or Multi-Instance Resource !" + msgError);
+ }
+ } else {
+ callback.onValidationError(toString(request), "Resource " + request.getVersionedId() +
+ ". This operation can only be used for ObjectInstance or Resource (multiple)");
}
- } else if (resultIds.isObjectInstance()) {
- /*
- * params = "{\"id\":0,\"resources\":[{\"id\":14,\"value\":\"+5\"},{\"id\":15,\"value\":\"+9\"}]}"
- * int rscId = resultIds.getObjectInstanceId();
- * contentFormat – Format of the payload (TLV or JSON).
- */
- Collection resources = client.getNewResourcesForInstance(request.getVersionedId(), request.getValue(), modelProvider, this.converter);
- if (resources.size() > 0) {
- ContentFormat contentFormat = request.getObjectContentFormat() != null ? request.getObjectContentFormat() : ContentFormat.DEFAULT;
- WriteRequest downlink = new WriteRequest(WriteRequest.Mode.UPDATE, contentFormat, resultIds.getObjectId(), resultIds.getObjectInstanceId(), resources);
- sendSimpleRequest(client, downlink, request.getTimeout(), callback);
+ } catch (Exception e) {
+ callback.onValidationError(toString(request), e.getMessage());
+ }
+ }
+
+ public void sendCreateRequest(LwM2mClient client, TbLwM2MCreateRequest request, DownlinkRequestCallback callback) {
+ validateVersionedId(client, request);
+ CreateRequest downlink = null;
+ LwM2mPath resultIds = new LwM2mPath(request.getObjectId());
+ ObjectModel objectModel = client.getObjectModel(request.getVersionedId(), modelProvider);
+ // POST /{Object ID}/{Object Instance ID} && Resources is Mandatory
+ if (objectModel != null) {
+ if (objectModel.multiple) {
+
+ // LwM2M CBOR, SenML CBOR, SenML JSON, or TLV (see [LwM2M-CORE])
+ ContentFormat contentFormat = getWriteRequestContentFormat(client, request, modelProvider);
+ if (resultIds.isObject() || resultIds.isObjectInstance()) {
+ Collection resources;
+ if (resultIds.isObject()) {
+ if (request.getValue() != null) {
+ resources = client.getNewResourcesForInstance(request.getVersionedId(), request.getValue(), modelProvider, this.converter);
+ downlink = new CreateRequest(contentFormat, resultIds.getObjectId(), resources);
+ } else if (request.getNodes() != null && request.getNodes().size() > 0) {
+ Set instances = ConcurrentHashMap.newKeySet();
+ request.getNodes().forEach((key, value) -> {
+ Collection resourcesForInstance = client.getNewResourcesForInstance(request.getVersionedId(), value, modelProvider, this.converter);
+ LwM2mObjectInstance instance = new LwM2mObjectInstance(Integer.parseInt(key), resourcesForInstance);
+ instances.add(instance);
+ });
+ LwM2mObjectInstance[] instanceArrays = instances.toArray(new LwM2mObjectInstance[instances.size()]);
+ downlink = new CreateRequest(contentFormat, resultIds.getObjectId(), instanceArrays);
+ }
+
+ } else {
+ resources = client.getNewResourcesForInstance(request.getVersionedId(), request.getValue(), modelProvider, this.converter);
+ LwM2mObjectInstance instance = new LwM2mObjectInstance(resultIds.getObjectInstanceId(), resources);
+ downlink = new CreateRequest(contentFormat, resultIds.getObjectId(), instance);
+ }
+ }
+ if (downlink != null) {
+ sendSimpleRequest(client, downlink, request.getTimeout(), callback);
+ } else {
+ callback.onValidationError(toString(request), "Path " + request.getVersionedId() +
+ ". Object must be Multiple !");
+ }
} else {
- callback.onValidationError(toString(request), "No resources to update!");
+ throw new IllegalArgumentException("Path " + request.getVersionedId() + ". Object must be Multiple !");
}
} else {
- callback.onValidationError(toString(request), "Update of the root level object is not supported yet!");
+ callback.onValidationError(toString(request), "Resource " + request.getVersionedId() +
+ " is not configured in the device profile!");
}
}
-
private , T extends LwM2mResponse> void sendSimpleRequest(LwM2mClient client, R request, long timeoutInMs, DownlinkRequestCallback callback) {
sendRequest(client, request, timeoutInMs, callback, r -> request.getPath().toString());
}
@@ -410,24 +559,6 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im
}
}
- private void validateVersionedId(LwM2mClient client, HasVersionedId request) {
- client.isValidObjectVersion(request.getVersionedId());
- if (request.getObjectId() == null) {
- throw new IllegalArgumentException("Specified object id is null!");
- }
- }
-
- private void validateVersionedIds(LwM2mClient client, HasVersionedIds request) {
- for (String versionedId : request.getVersionedIds()) {
- client.isValidObjectVersion(versionedId);
- }
- for (String objectId : request.getObjectIds()) {
- if (objectId == null) {
- throw new IllegalArgumentException("Specified object id is null!");
- }
- }
- }
-
private static void addAttribute(List attributes, String attributeName, T value) {
addAttribute(attributes, attributeName, value, null, null);
}
@@ -442,52 +573,82 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im
}
}
- private static ContentFormat convertResourceModelTypeToContentFormat(LwM2mClient client, ResourceModel.Type type) {
- switch (type) {
- case BOOLEAN:
- case STRING:
- case TIME:
- case INTEGER:
- case FLOAT:
- return client.getDefaultContentFormat();
- case OPAQUE:
- return ContentFormat.OPAQUE;
- case OBJLNK:
- return ContentFormat.LINK;
- default:
+ private static ContentFormat getReadRequestContentFormat(LwM2mClient client, T request, LwM2mModelProvider modelProvider) {
+ if (request.getRequestContentFormat().isPresent()) {
+ return request.getRequestContentFormat().get();
+ } else {
+ return getRequestContentFormat(client, request.getVersionedId(), modelProvider);
}
- throw new CodecException("Invalid ResourceModel_Type for %s ContentFormat.", type);
}
- private static ContentFormat getRequestContentFormat(LwM2mClient client, HasContentFormat request, LwM2mModelProvider modelProvider) {
- if (request.getRequestContentFormat() != null) {
- return request.getRequestContentFormat();
+ private static ContentFormat getWriteRequestContentFormat(LwM2mClient client, TbLwM2MDownlinkRequest request, LwM2mModelProvider modelProvider) {
+ if (request instanceof TbLwM2MWriteReplaceRequest && ((TbLwM2MWriteReplaceRequest) request).getContentFormat() != null) {
+ return ((TbLwM2MWriteReplaceRequest) request).getContentFormat();
+ } else if (request instanceof TbLwM2MWriteUpdateRequest && ((TbLwM2MWriteUpdateRequest) request).getObjectContentFormat() != null) {
+ return ((TbLwM2MWriteUpdateRequest) request).getObjectContentFormat();
} else {
String versionedId = null;
- if (request instanceof TbLwM2MReadRequest) {
- versionedId = ((TbLwM2MReadRequest) request).getVersionedId();
- } else if (request instanceof TbLwM2MObserveRequest) {
- versionedId = ((TbLwM2MObserveRequest) request).getVersionedId();
+ if (request instanceof TbLwM2MWriteReplaceRequest) {
+ versionedId = ((TbLwM2MWriteReplaceRequest) request).getVersionedId();
+ } else if (request instanceof TbLwM2MWriteUpdateRequest) {
+ versionedId = ((TbLwM2MWriteUpdateRequest) request).getVersionedId();
+ } else if (request instanceof TbLwM2MCreateRequest) {
+ versionedId = ((TbLwM2MCreateRequest) request).getVersionedId();
+ }
+ return getRequestContentFormat(client, versionedId, modelProvider);
+ }
+ }
+
+ private static ContentFormat getRequestContentFormat(LwM2mClient client, String versionedId, LwM2mModelProvider modelProvider) {
+ LwM2mPath pathIds = new LwM2mPath(fromVersionedIdToObjectId(versionedId));
+ if (pathIds.isResource() || pathIds.isResourceInstance()) {
+ ResourceModel resourceModel = client.getResourceModel(versionedId, modelProvider);
+ if (resourceModel != null && (pathIds.isResourceInstance() || (pathIds.isResource() && !resourceModel.multiple))) {
+ if (OBJLNK.equals(resourceModel.type)) {
+ return ContentFormat.LINK;
+ } else if (OPAQUE.equals(resourceModel.type)) {
+ return ContentFormat.OPAQUE;
+ } else {
+ return findFirst(client.getClientSupportContentFormats(), client.getDefaultContentFormat(), ContentFormat.CBOR, ContentFormat.SENML_CBOR, ContentFormat.SENML_JSON);
+ }
+ } else {
+ return getContentFormatForComplex(client);
}
- String id = fromVersionedIdToObjectId(versionedId);
- if (id != null && new LwM2mPath(id).isResource() && !client.isResourceMultiInstances(versionedId, modelProvider)) {
- return client.getDefaultContentFormat();
+ } else {
+ return getContentFormatForComplex(client);
+ }
+ }
+
+ private static ContentFormat getContentFormatForComplex(LwM2mClient client) {
+ if (LwM2m.Version.V1_0.equals(client.getRegistration().getLwM2mVersion())) {
+ return ContentFormat.TLV;
+ } else if (LwM2m.Version.V1_1.equals(client.getRegistration().getLwM2mVersion())) {
+ ContentFormat result = findFirst(client.getClientSupportContentFormats(), null, ContentFormat.SENML_CBOR, ContentFormat.SENML_JSON, ContentFormat.TLV, ContentFormat.JSON);
+ if (result != null) {
+ return result;
} else {
- return ContentFormat.DEFAULT;
+ throw new RuntimeException("The client does not support any of SenML CBOR, SenML JSON, TLV or JSON formats. Can't send complex requests. Try using singe-instance requests.");
}
+ } else {
+ throw new RuntimeException("The version " + client.getRegistration().getLwM2mVersion() + " is not supported!");
}
}
+ private static ContentFormat findFirst(Set supported, ContentFormat defaultValue, ContentFormat... desiredFormats) {
+ for (ContentFormat contentFormat : desiredFormats) {
+ if (supported.contains(contentFormat)) {
+ return contentFormat;
+ }
+ }
+ return defaultValue;
+ }
+
private String toString(R request) {
try {
- try {
- return JacksonUtil.toString(request);
- } catch (Exception e) {
- return request.toString();
- }
+ return request != null ? request.toString() : "";
} catch (Exception e) {
- log.warn("Failed to convert request to string", e);
- return request != null ? request.getClass().getSimpleName() : "";
+ log.debug("Failed to convert request to string", e);
+ return request.getClass().getSimpleName();
}
}
}
diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/DownlinkRequestCallback.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/DownlinkRequestCallback.java
index 8912c51960..40cf896f55 100644
--- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/DownlinkRequestCallback.java
+++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/DownlinkRequestCallback.java
@@ -17,9 +17,9 @@ package org.thingsboard.server.transport.lwm2m.server.downlink;
public interface DownlinkRequestCallback {
- default boolean onSent(R request){
+ default boolean onSent(R request) {
return true;
- };
+ }
void onSuccess(R request, T response);
diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/HasContentFormat.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/HasContentFormat.java
index f2618224e7..833ff76cab 100644
--- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/HasContentFormat.java
+++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/HasContentFormat.java
@@ -17,9 +17,11 @@ package org.thingsboard.server.transport.lwm2m.server.downlink;
import org.eclipse.leshan.core.request.ContentFormat;
+import java.util.Optional;
+
public interface HasContentFormat {
- ContentFormat getRequestContentFormat();
+ Optional getRequestContentFormat();
default ContentFormat getResponseContentFormat() {
return null;
diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/HasVersionedId.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/HasVersionedId.java
index fcbb195935..7e4c25a82d 100644
--- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/HasVersionedId.java
+++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/HasVersionedId.java
@@ -15,14 +15,14 @@
*/
package org.thingsboard.server.transport.lwm2m.server.downlink;
-import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil;
+import org.thingsboard.server.transport.lwm2m.utils.LwM2MTransportUtil;
public interface HasVersionedId {
String getVersionedId();
default String getObjectId(){
- return LwM2mTransportUtil.fromVersionedIdToObjectId(getVersionedId());
+ return LwM2MTransportUtil.fromVersionedIdToObjectId(getVersionedId());
}
}
diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/HasVersionedIds.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/HasVersionedIds.java
index 5ccef5ecea..3dda62669f 100644
--- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/HasVersionedIds.java
+++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/HasVersionedIds.java
@@ -15,7 +15,7 @@
*/
package org.thingsboard.server.transport.lwm2m.server.downlink;
-import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil;
+import org.thingsboard.server.transport.lwm2m.utils.LwM2MTransportUtil;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
@@ -27,7 +27,7 @@ public interface HasVersionedIds {
default String[] getObjectIds() {
Set objectIds = ConcurrentHashMap.newKeySet();
for (String versionedId : getVersionedIds()) {
- objectIds.add(LwM2mTransportUtil.fromVersionedIdToObjectId(versionedId));
+ objectIds.add(LwM2MTransportUtil.fromVersionedIdToObjectId(versionedId));
}
return objectIds.toArray(String[]::new);
}
diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/LwM2mDownlinkMsgHandler.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/LwM2mDownlinkMsgHandler.java
index 871a59a63b..a4537af703 100644
--- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/LwM2mDownlinkMsgHandler.java
+++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/LwM2mDownlinkMsgHandler.java
@@ -16,6 +16,8 @@
package org.thingsboard.server.transport.lwm2m.server.downlink;
import org.eclipse.leshan.core.Link;
+import org.eclipse.leshan.core.request.ContentFormat;
+import org.eclipse.leshan.core.request.CreateRequest;
import org.eclipse.leshan.core.request.DeleteRequest;
import org.eclipse.leshan.core.request.DiscoverRequest;
import org.eclipse.leshan.core.request.ExecuteRequest;
@@ -25,6 +27,7 @@ import org.eclipse.leshan.core.request.ReadRequest;
import org.eclipse.leshan.core.request.WriteAttributesRequest;
import org.eclipse.leshan.core.request.WriteCompositeRequest;
import org.eclipse.leshan.core.request.WriteRequest;
+import org.eclipse.leshan.core.response.CreateResponse;
import org.eclipse.leshan.core.response.DeleteResponse;
import org.eclipse.leshan.core.response.DiscoverResponse;
import org.eclipse.leshan.core.response.ExecuteResponse;
@@ -45,7 +48,7 @@ public interface LwM2mDownlinkMsgHandler {
void sendReadRequest(LwM2mClient client, TbLwM2MReadRequest request, DownlinkRequestCallback callback);
- void sendReadCompositeRequest(LwM2mClient client, TbLwM2MReadCompositeRequest request, DownlinkRequestCallback callback);
+ void sendReadCompositeRequest(LwM2mClient client, TbLwM2MReadCompositeRequest request, DownlinkRequestCallback callback, ContentFormat contentFormatComposite);
void sendObserveRequest(LwM2mClient client, TbLwM2MObserveRequest request, DownlinkRequestCallback callback);
@@ -67,9 +70,10 @@ public interface LwM2mDownlinkMsgHandler {
void sendWriteReplaceRequest(LwM2mClient client, TbLwM2MWriteReplaceRequest request, DownlinkRequestCallback callback);
- void sendWriteCompositeRequest(LwM2mClient client, RpcWriteCompositeRequest nodes, DownlinkRequestCallback callback);
+ void sendWriteCompositeRequest(LwM2mClient client, RpcWriteCompositeRequest nodes, DownlinkRequestCallback callback, ContentFormat contentFormatComposite);
void sendWriteUpdateRequest(LwM2mClient client, TbLwM2MWriteUpdateRequest request, DownlinkRequestCallback callback);
+ void sendCreateRequest(LwM2mClient client, TbLwM2MCreateRequest request, DownlinkRequestCallback callback);
}
diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MCancelAllObserveCallback.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MCancelAllObserveCallback.java
index f90e0f8b97..961d6db928 100644
--- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MCancelAllObserveCallback.java
+++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MCancelAllObserveCallback.java
@@ -19,7 +19,7 @@ import lombok.extern.slf4j.Slf4j;
import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
import org.thingsboard.server.transport.lwm2m.server.log.LwM2MTelemetryLogService;
-import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LWM2M_INFO;
+import static org.thingsboard.server.transport.lwm2m.utils.LwM2MTransportUtil.LOG_LWM2M_INFO;
@Slf4j
public class TbLwM2MCancelAllObserveCallback extends AbstractTbLwM2MRequestCallback {
diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MCancelAllRequest.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MCancelAllRequest.java
index f4e02e6222..4d80b0932e 100644
--- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MCancelAllRequest.java
+++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MCancelAllRequest.java
@@ -17,7 +17,7 @@ package org.thingsboard.server.transport.lwm2m.server.downlink;
import lombok.Builder;
import lombok.Getter;
-import org.thingsboard.server.transport.lwm2m.server.LwM2mOperationType;
+import org.thingsboard.server.transport.lwm2m.server.LwM2MOperationType;
public class TbLwM2MCancelAllRequest implements TbLwM2MDownlinkRequest {
@@ -30,8 +30,8 @@ public class TbLwM2MCancelAllRequest implements TbLwM2MDownlinkRequest
}
@Override
- public LwM2mOperationType getType() {
- return LwM2mOperationType.OBSERVE_CANCEL_ALL;
+ public LwM2MOperationType getType() {
+ return LwM2MOperationType.OBSERVE_CANCEL_ALL;
}
}
diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MCancelObserveCallback.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MCancelObserveCallback.java
index 311be03462..9647519cf0 100644
--- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MCancelObserveCallback.java
+++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MCancelObserveCallback.java
@@ -16,12 +16,10 @@
package org.thingsboard.server.transport.lwm2m.server.downlink;
import lombok.extern.slf4j.Slf4j;
-import org.thingsboard.server.transport.lwm2m.server.log.LwM2MTelemetryLogService;
-import org.thingsboard.server.transport.lwm2m.server.uplink.LwM2mUplinkMsgHandler;
import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
+import org.thingsboard.server.transport.lwm2m.server.log.LwM2MTelemetryLogService;
-import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LWM2M_INFO;
-import static org.thingsboard.server.transport.lwm2m.server.LwM2mOperationType.OBSERVE_CANCEL;
+import static org.thingsboard.server.transport.lwm2m.utils.LwM2MTransportUtil.LOG_LWM2M_INFO;
@Slf4j
public class TbLwM2MCancelObserveCallback extends AbstractTbLwM2MRequestCallback {
diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MCancelObserveRequest.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MCancelObserveRequest.java
index cb4d056578..dd243e2a2e 100644
--- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MCancelObserveRequest.java
+++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MCancelObserveRequest.java
@@ -16,7 +16,7 @@
package org.thingsboard.server.transport.lwm2m.server.downlink;
import lombok.Builder;
-import org.thingsboard.server.transport.lwm2m.server.LwM2mOperationType;
+import org.thingsboard.server.transport.lwm2m.server.LwM2MOperationType;
public class TbLwM2MCancelObserveRequest extends AbstractTbLwM2MTargetedDownlinkRequest {
@@ -26,8 +26,8 @@ public class TbLwM2MCancelObserveRequest extends AbstractTbLwM2MTargetedDownlink
}
@Override
- public LwM2mOperationType getType() {
- return LwM2mOperationType.OBSERVE_CANCEL;
+ public LwM2MOperationType getType() {
+ return LwM2MOperationType.OBSERVE_CANCEL;
}
diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MCreateRequest.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MCreateRequest.java
new file mode 100644
index 0000000000..ecc66c20f9
--- /dev/null
+++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MCreateRequest.java
@@ -0,0 +1,47 @@
+/**
+ * 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.downlink;
+
+import lombok.Builder;
+import lombok.Getter;
+import org.eclipse.leshan.core.request.ContentFormat;
+import org.eclipse.leshan.core.response.CreateResponse;
+import org.thingsboard.server.transport.lwm2m.server.LwM2MOperationType;
+
+import java.util.Map;
+
+public class TbLwM2MCreateRequest extends AbstractTbLwM2MTargetedDownlinkRequest {
+
+ @Getter
+ private final Object value;
+ @Getter
+ private final ContentFormat objectContentFormat;
+ @Getter
+ private final Map nodes;
+
+ @Builder
+ private TbLwM2MCreateRequest(String versionedId, long timeout, Object value, ContentFormat objectContentFormat, Map nodes) {
+ super(versionedId, timeout);
+ this.value = value;
+ this.objectContentFormat = objectContentFormat;
+ this.nodes = nodes;
+ }
+
+ @Override
+ public LwM2MOperationType getType() {
+ return LwM2MOperationType.CREATE;
+ }
+}
diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MCreateResponseCallback.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MCreateResponseCallback.java
new file mode 100644
index 0000000000..316bbd4636
--- /dev/null
+++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MCreateResponseCallback.java
@@ -0,0 +1,36 @@
+/**
+ * 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.downlink;
+
+import org.eclipse.leshan.core.request.CreateRequest;
+import org.eclipse.leshan.core.response.CreateResponse;
+import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
+import org.thingsboard.server.transport.lwm2m.server.log.LwM2MTelemetryLogService;
+import org.thingsboard.server.transport.lwm2m.server.uplink.LwM2mUplinkMsgHandler;
+
+public class TbLwM2MCreateResponseCallback extends TbLwM2MUplinkTargetedCallback {
+
+ public TbLwM2MCreateResponseCallback(LwM2mUplinkMsgHandler handler, LwM2MTelemetryLogService logService, LwM2mClient client, String targetId) {
+ super(handler, logService, client, targetId);
+ }
+
+ @Override
+ public void onSuccess(CreateRequest request, CreateResponse response) {
+ super.onSuccess(request, response);
+ handler.onCreateResponseOk(client, versionedId, request);
+ }
+
+}
diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MDeleteCallback.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MDeleteCallback.java
index 4c0a758572..2b3c544dae 100644
--- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MDeleteCallback.java
+++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MDeleteCallback.java
@@ -19,7 +19,6 @@ import org.eclipse.leshan.core.request.DeleteRequest;
import org.eclipse.leshan.core.response.DeleteResponse;
import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
import org.thingsboard.server.transport.lwm2m.server.log.LwM2MTelemetryLogService;
-import org.thingsboard.server.transport.lwm2m.server.uplink.LwM2mUplinkMsgHandler;
public class TbLwM2MDeleteCallback extends TbLwM2MTargetedCallback {
diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MDeleteRequest.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MDeleteRequest.java
index b9649c0708..053106ca2d 100644
--- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MDeleteRequest.java
+++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MDeleteRequest.java
@@ -17,7 +17,7 @@ package org.thingsboard.server.transport.lwm2m.server.downlink;
import lombok.Builder;
import org.eclipse.leshan.core.response.ReadResponse;
-import org.thingsboard.server.transport.lwm2m.server.LwM2mOperationType;
+import org.thingsboard.server.transport.lwm2m.server.LwM2MOperationType;
public class TbLwM2MDeleteRequest extends AbstractTbLwM2MTargetedDownlinkRequest {
@@ -27,8 +27,8 @@ public class TbLwM2MDeleteRequest extends AbstractTbLwM2MTargetedDownlinkRequest
}
@Override
- public LwM2mOperationType getType() {
- return LwM2mOperationType.DELETE;
+ public LwM2MOperationType getType() {
+ return LwM2MOperationType.DELETE;
}
diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MDiscoverAllRequest.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MDiscoverAllRequest.java
index 291bdc907c..bf29a0c027 100644
--- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MDiscoverAllRequest.java
+++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MDiscoverAllRequest.java
@@ -17,7 +17,7 @@ package org.thingsboard.server.transport.lwm2m.server.downlink;
import lombok.Builder;
import lombok.Getter;
-import org.thingsboard.server.transport.lwm2m.server.LwM2mOperationType;
+import org.thingsboard.server.transport.lwm2m.server.LwM2MOperationType;
public class TbLwM2MDiscoverAllRequest implements TbLwM2MDownlinkRequest {
@@ -30,8 +30,8 @@ public class TbLwM2MDiscoverAllRequest implements TbLwM2MDownlinkRequest
}
@Override
- public LwM2mOperationType getType() {
- return LwM2mOperationType.DISCOVER_ALL;
+ public LwM2MOperationType getType() {
+ return LwM2MOperationType.DISCOVER_ALL;
}
diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MDiscoverCallback.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MDiscoverCallback.java
index 41172f0599..cc855fd3a8 100644
--- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MDiscoverCallback.java
+++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MDiscoverCallback.java
@@ -17,9 +17,8 @@ package org.thingsboard.server.transport.lwm2m.server.downlink;
import org.eclipse.leshan.core.request.DiscoverRequest;
import org.eclipse.leshan.core.response.DiscoverResponse;
-import org.thingsboard.server.transport.lwm2m.server.log.LwM2MTelemetryLogService;
-import org.thingsboard.server.transport.lwm2m.server.uplink.LwM2mUplinkMsgHandler;
import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
+import org.thingsboard.server.transport.lwm2m.server.log.LwM2MTelemetryLogService;
public class TbLwM2MDiscoverCallback extends TbLwM2MTargetedCallback {
diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MDiscoverRequest.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MDiscoverRequest.java
index 85aa75de3c..b4a5975ec4 100644
--- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MDiscoverRequest.java
+++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MDiscoverRequest.java
@@ -17,7 +17,7 @@ package org.thingsboard.server.transport.lwm2m.server.downlink;
import lombok.Builder;
import org.eclipse.leshan.core.response.DiscoverResponse;
-import org.thingsboard.server.transport.lwm2m.server.LwM2mOperationType;
+import org.thingsboard.server.transport.lwm2m.server.LwM2MOperationType;
public class TbLwM2MDiscoverRequest extends AbstractTbLwM2MTargetedDownlinkRequest {
@@ -27,8 +27,8 @@ public class TbLwM2MDiscoverRequest extends AbstractTbLwM2MTargetedDownlinkReque
}
@Override
- public LwM2mOperationType getType() {
- return LwM2mOperationType.DISCOVER;
+ public LwM2MOperationType getType() {
+ return LwM2MOperationType.DISCOVER;
}
diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MDownlinkRequest.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MDownlinkRequest.java
index 3ea174c72d..43e532a380 100644
--- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MDownlinkRequest.java
+++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MDownlinkRequest.java
@@ -15,11 +15,11 @@
*/
package org.thingsboard.server.transport.lwm2m.server.downlink;
-import org.thingsboard.server.transport.lwm2m.server.LwM2mOperationType;
+import org.thingsboard.server.transport.lwm2m.server.LwM2MOperationType;
public interface TbLwM2MDownlinkRequest {
- LwM2mOperationType getType();
+ LwM2MOperationType getType();
long getTimeout();
diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MExecuteCallback.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MExecuteCallback.java
index 992cf6d616..9315e9ded6 100644
--- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MExecuteCallback.java
+++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MExecuteCallback.java
@@ -17,9 +17,8 @@ package org.thingsboard.server.transport.lwm2m.server.downlink;
import org.eclipse.leshan.core.request.ExecuteRequest;
import org.eclipse.leshan.core.response.ExecuteResponse;
-import org.thingsboard.server.transport.lwm2m.server.log.LwM2MTelemetryLogService;
-import org.thingsboard.server.transport.lwm2m.server.uplink.LwM2mUplinkMsgHandler;
import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
+import org.thingsboard.server.transport.lwm2m.server.log.LwM2MTelemetryLogService;
public class TbLwM2MExecuteCallback extends TbLwM2MTargetedCallback {
diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MExecuteRequest.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MExecuteRequest.java
index 76cf8cd0eb..dbdc692f53 100644
--- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MExecuteRequest.java
+++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MExecuteRequest.java
@@ -18,7 +18,7 @@ package org.thingsboard.server.transport.lwm2m.server.downlink;
import lombok.Builder;
import lombok.Getter;
import org.eclipse.leshan.core.response.ReadResponse;
-import org.thingsboard.server.transport.lwm2m.server.LwM2mOperationType;
+import org.thingsboard.server.transport.lwm2m.server.LwM2MOperationType;
public class TbLwM2MExecuteRequest extends AbstractTbLwM2MTargetedDownlinkRequest {
@@ -32,8 +32,8 @@ public class TbLwM2MExecuteRequest extends AbstractTbLwM2MTargetedDownlinkReques
}
@Override
- public LwM2mOperationType getType() {
- return LwM2mOperationType.EXECUTE;
+ public LwM2MOperationType getType() {
+ return LwM2MOperationType.EXECUTE;
}
diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MObserveAllRequest.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MObserveAllRequest.java
index 2aba4f0a58..4813d38181 100644
--- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MObserveAllRequest.java
+++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MObserveAllRequest.java
@@ -17,7 +17,7 @@ package org.thingsboard.server.transport.lwm2m.server.downlink;
import lombok.Builder;
import lombok.Getter;
-import org.thingsboard.server.transport.lwm2m.server.LwM2mOperationType;
+import org.thingsboard.server.transport.lwm2m.server.LwM2MOperationType;
import java.util.Set;
@@ -32,8 +32,8 @@ public class TbLwM2MObserveAllRequest implements TbLwM2MDownlinkRequest {
diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MObserveRequest.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MObserveRequest.java
index 0d13b4a1ff..1c41a48b2f 100644
--- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MObserveRequest.java
+++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MObserveRequest.java
@@ -16,27 +16,30 @@
package org.thingsboard.server.transport.lwm2m.server.downlink;
import lombok.Builder;
-import lombok.Getter;
import org.eclipse.leshan.core.request.ContentFormat;
import org.eclipse.leshan.core.response.ObserveResponse;
-import org.thingsboard.server.transport.lwm2m.server.LwM2mOperationType;
+import org.thingsboard.server.transport.lwm2m.server.LwM2MOperationType;
+
+import java.util.Optional;
public class TbLwM2MObserveRequest extends AbstractTbLwM2MTargetedDownlinkRequest implements HasContentFormat {
- @Getter
- private final ContentFormat requestContentFormat;
+ private final Optional requestContentFormat;
@Builder
private TbLwM2MObserveRequest(String versionedId, long timeout, ContentFormat requestContentFormat) {
super(versionedId, timeout);
- this.requestContentFormat = requestContentFormat;
+ this.requestContentFormat = Optional.ofNullable(requestContentFormat);
}
@Override
- public LwM2mOperationType getType() {
- return LwM2mOperationType.OBSERVE;
+ public LwM2MOperationType getType() {
+ return LwM2MOperationType.OBSERVE;
}
-
+ @Override
+ public Optional getRequestContentFormat() {
+ return this.requestContentFormat;
+ }
}
diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MReadCallback.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MReadCallback.java
index 59247b103b..033e9c12bf 100644
--- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MReadCallback.java
+++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MReadCallback.java
@@ -16,8 +16,11 @@
package org.thingsboard.server.transport.lwm2m.server.downlink;
import lombok.extern.slf4j.Slf4j;
+import org.eclipse.leshan.core.model.ResourceModel;
+import org.eclipse.leshan.core.node.LwM2mSingleResource;
import org.eclipse.leshan.core.request.ReadRequest;
import org.eclipse.leshan.core.response.ReadResponse;
+import org.eclipse.leshan.core.util.Hex;
import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
import org.thingsboard.server.transport.lwm2m.server.log.LwM2MTelemetryLogService;
import org.thingsboard.server.transport.lwm2m.server.uplink.LwM2mUplinkMsgHandler;
@@ -31,8 +34,25 @@ public class TbLwM2MReadCallback extends TbLwM2MUplinkTargetedCallback 0) {
+ String valueReplace = len + "Bytes";
+ String valueStr = Hex.encodeHexString(valueInBytes);
+ return response.toString().replace(valueReplace, valueStr);
+ }
+ }
+ }
+ return response.toString();
+ }
+
}
diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MReadRequest.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MReadRequest.java
index 6f388237c2..5e5ffb163a 100644
--- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MReadRequest.java
+++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MReadRequest.java
@@ -16,27 +16,30 @@
package org.thingsboard.server.transport.lwm2m.server.downlink;
import lombok.Builder;
-import lombok.Getter;
import org.eclipse.leshan.core.request.ContentFormat;
import org.eclipse.leshan.core.response.ReadResponse;
-import org.thingsboard.server.transport.lwm2m.server.LwM2mOperationType;
+import org.thingsboard.server.transport.lwm2m.server.LwM2MOperationType;
+
+import java.util.Optional;
public class TbLwM2MReadRequest extends AbstractTbLwM2MTargetedDownlinkRequest implements HasContentFormat {
- @Getter
- private final ContentFormat requestContentFormat;
+ private final Optional requestContentFormat;
@Builder
private TbLwM2MReadRequest(String versionedId, long timeout, ContentFormat requestContentFormat) {
super(versionedId, timeout);
- this.requestContentFormat = requestContentFormat;
+ this.requestContentFormat = Optional.ofNullable(requestContentFormat);
}
@Override
- public LwM2mOperationType getType() {
- return LwM2mOperationType.READ;
+ public LwM2MOperationType getType() {
+ return LwM2MOperationType.READ;
}
-
+ @Override
+ public Optional getRequestContentFormat() {
+ return this.requestContentFormat;
+ }
}
diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MTargetedCallback.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MTargetedCallback.java
index 6b013ef9b5..cf33a5857f 100644
--- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MTargetedCallback.java
+++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MTargetedCallback.java
@@ -16,12 +16,16 @@
package org.thingsboard.server.transport.lwm2m.server.downlink;
import lombok.extern.slf4j.Slf4j;
+import org.eclipse.leshan.core.ResponseCode;
+import org.eclipse.leshan.core.response.LwM2mResponse;
+import org.eclipse.leshan.core.response.ReadResponse;
import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
import org.thingsboard.server.transport.lwm2m.server.log.LwM2MTelemetryLogService;
import java.util.Arrays;
-import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LWM2M_INFO;
+import static org.thingsboard.server.transport.lwm2m.utils.LwM2MTransportUtil.LOG_LWM2M_ERROR;
+import static org.thingsboard.server.transport.lwm2m.utils.LwM2MTransportUtil.LOG_LWM2M_INFO;
@Slf4j
public abstract class TbLwM2MTargetedCallback extends AbstractTbLwM2MRequestCallback {
@@ -44,9 +48,22 @@ public abstract class TbLwM2MTargetedCallback extends AbstractTbLwM2MReque
@Override
public void onSuccess(R request, T response) {
//TODO convert camelCase to "camel case" using .split("(? ResponseCode.CONTENT_CODE) {
+ log.error("[{}] [{}] [{}] failed to process successful response [{}] ", client.getEndpoint(), requestName,
+ versionedId != null ? versionedId : Arrays.toString(versionedIds), responseStr);
+ logService.log(client, String.format("[%s]: %s [%s] failed to process successful. Result: %s", LOG_LWM2M_ERROR,
+ requestName, versionedId != null ? versionedId : Arrays.toString(versionedIds), responseStr));
+ } else {
+ log.trace("[{}] {} [{}] successful: {}", client.getEndpoint(), requestName, versionedId != null ?
+ versionedId : versionedIds, responseStr);
+ logService.log(client, String.format("[%s]: %s [%s] successful. Result: %s", LOG_LWM2M_INFO, requestName,
+ versionedId != null ? versionedId : Arrays.toString(versionedIds), responseStr));
+ }
+ }
}
diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MWriteAttributesCallback.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MWriteAttributesCallback.java
index e346ad965a..3e4847ce1e 100644
--- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MWriteAttributesCallback.java
+++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MWriteAttributesCallback.java
@@ -19,7 +19,6 @@ import org.eclipse.leshan.core.request.WriteAttributesRequest;
import org.eclipse.leshan.core.response.WriteAttributesResponse;
import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
import org.thingsboard.server.transport.lwm2m.server.log.LwM2MTelemetryLogService;
-import org.thingsboard.server.transport.lwm2m.server.uplink.LwM2mUplinkMsgHandler;
public class TbLwM2MWriteAttributesCallback extends TbLwM2MTargetedCallback {
diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MWriteAttributesRequest.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MWriteAttributesRequest.java
index 6ef198a28f..7d0436b1b8 100644
--- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MWriteAttributesRequest.java
+++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MWriteAttributesRequest.java
@@ -18,8 +18,8 @@ package org.thingsboard.server.transport.lwm2m.server.downlink;
import lombok.Builder;
import lombok.Getter;
import org.eclipse.leshan.core.response.WriteAttributesResponse;
-import org.thingsboard.server.common.data.device.data.lwm2m.ObjectAttributes;
-import org.thingsboard.server.transport.lwm2m.server.LwM2mOperationType;
+import org.thingsboard.server.common.data.device.profile.lwm2m.ObjectAttributes;
+import org.thingsboard.server.transport.lwm2m.server.LwM2MOperationType;
public class TbLwM2MWriteAttributesRequest extends AbstractTbLwM2MTargetedDownlinkRequest {
@@ -33,8 +33,8 @@ public class TbLwM2MWriteAttributesRequest extends AbstractTbLwM2MTargetedDownli
}
@Override
- public LwM2mOperationType getType() {
- return LwM2mOperationType.WRITE_ATTRIBUTES;
+ public LwM2MOperationType getType() {
+ return LwM2MOperationType.WRITE_ATTRIBUTES;
}
diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MWriteReplaceRequest.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MWriteReplaceRequest.java
index f4b1059944..9760e13e5a 100644
--- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MWriteReplaceRequest.java
+++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MWriteReplaceRequest.java
@@ -19,7 +19,7 @@ import lombok.Builder;
import lombok.Getter;
import org.eclipse.leshan.core.request.ContentFormat;
import org.eclipse.leshan.core.response.WriteResponse;
-import org.thingsboard.server.transport.lwm2m.server.LwM2mOperationType;
+import org.thingsboard.server.transport.lwm2m.server.LwM2MOperationType;
public class TbLwM2MWriteReplaceRequest extends AbstractTbLwM2MTargetedDownlinkRequest {
@@ -36,8 +36,8 @@ public class TbLwM2MWriteReplaceRequest extends AbstractTbLwM2MTargetedDownlinkR
}
@Override
- public LwM2mOperationType getType() {
- return LwM2mOperationType.WRITE_REPLACE;
+ public LwM2MOperationType getType() {
+ return LwM2MOperationType.WRITE_REPLACE;
}
diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MWriteResponseCallback.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MWriteResponseCallback.java
index 4746077f19..a452c3b187 100644
--- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MWriteResponseCallback.java
+++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MWriteResponseCallback.java
@@ -15,12 +15,14 @@
*/
package org.thingsboard.server.transport.lwm2m.server.downlink;
+import lombok.extern.slf4j.Slf4j;
import org.eclipse.leshan.core.request.WriteRequest;
import org.eclipse.leshan.core.response.WriteResponse;
import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
import org.thingsboard.server.transport.lwm2m.server.log.LwM2MTelemetryLogService;
import org.thingsboard.server.transport.lwm2m.server.uplink.LwM2mUplinkMsgHandler;
+@Slf4j
public class TbLwM2MWriteResponseCallback extends TbLwM2MUplinkTargetedCallback {
public TbLwM2MWriteResponseCallback(LwM2mUplinkMsgHandler handler, LwM2MTelemetryLogService logService, LwM2mClient client, String targetId) {
@@ -30,7 +32,7 @@ public class TbLwM2MWriteResponseCallback extends TbLwM2MUplinkTargetedCallback<
@Override
public void onSuccess(WriteRequest request, WriteResponse response) {
super.onSuccess(request, response);
- handler.onWriteResponseOk(client, versionedId, request);
+ handler.onWriteResponseOk(client, versionedId, request, response.getCode().getCode());
}
}
diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MWriteUpdateRequest.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MWriteUpdateRequest.java
index a9465e082d..6e8708053b 100644
--- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MWriteUpdateRequest.java
+++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MWriteUpdateRequest.java
@@ -19,7 +19,7 @@ import lombok.Builder;
import lombok.Getter;
import org.eclipse.leshan.core.request.ContentFormat;
import org.eclipse.leshan.core.response.WriteResponse;
-import org.thingsboard.server.transport.lwm2m.server.LwM2mOperationType;
+import org.thingsboard.server.transport.lwm2m.server.LwM2MOperationType;
public class TbLwM2MWriteUpdateRequest extends AbstractTbLwM2MTargetedDownlinkRequest {
@@ -36,8 +36,8 @@ public class TbLwM2MWriteUpdateRequest extends AbstractTbLwM2MTargetedDownlinkRe
}
@Override
- public LwM2mOperationType getType() {
- return LwM2mOperationType.WRITE_UPDATE;
+ public LwM2MOperationType getType() {
+ return LwM2MOperationType.WRITE_UPDATE;
}
diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/composite/TbLwM2MReadCompositeRequest.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/composite/TbLwM2MReadCompositeRequest.java
index 43b55f371f..f9c4afcc40 100644
--- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/composite/TbLwM2MReadCompositeRequest.java
+++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/composite/TbLwM2MReadCompositeRequest.java
@@ -19,13 +19,15 @@ import lombok.Builder;
import lombok.Getter;
import org.eclipse.leshan.core.request.ContentFormat;
import org.eclipse.leshan.core.response.ReadCompositeResponse;
-import org.thingsboard.server.transport.lwm2m.server.LwM2mOperationType;
+import org.thingsboard.server.transport.lwm2m.server.LwM2MOperationType;
import org.thingsboard.server.transport.lwm2m.server.downlink.HasContentFormat;
+import java.util.Optional;
+
public class TbLwM2MReadCompositeRequest extends AbstractTbLwM2MTargetedDownlinkCompositeRequest implements HasContentFormat {
- @Getter
- private final ContentFormat requestContentFormat;
+
+ private final Optional requestContentFormatOpt;
@Getter
private final ContentFormat responseContentFormat;
@@ -33,12 +35,17 @@ public class TbLwM2MReadCompositeRequest extends AbstractTbLwM2MTargetedDownlink
@Builder
private TbLwM2MReadCompositeRequest(String [] versionedIds, long timeout, ContentFormat requestContentFormat, ContentFormat responseContentFormat) {
super(versionedIds, timeout);
- this.requestContentFormat = requestContentFormat;
+ this.requestContentFormatOpt = Optional.ofNullable(requestContentFormat);
this.responseContentFormat = responseContentFormat;
}
@Override
- public LwM2mOperationType getType() {
- return LwM2mOperationType.READ_COMPOSITE;
+ public LwM2MOperationType getType() {
+ return LwM2MOperationType.READ_COMPOSITE;
+ }
+
+ @Override
+ public Optional getRequestContentFormat() {
+ return this.requestContentFormatOpt;
}
}
diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/composite/TbLwM2MWriteCompositeRequest.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/composite/TbLwM2MWriteCompositeRequest.java
index 0e3ffaed28..c3fe137cae 100644
--- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/composite/TbLwM2MWriteCompositeRequest.java
+++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/composite/TbLwM2MWriteCompositeRequest.java
@@ -19,7 +19,7 @@ import lombok.Builder;
import lombok.Getter;
import org.eclipse.leshan.core.request.ContentFormat;
import org.eclipse.leshan.core.response.WriteCompositeResponse;
-import org.thingsboard.server.transport.lwm2m.server.LwM2mOperationType;
+import org.thingsboard.server.transport.lwm2m.server.LwM2MOperationType;
import org.thingsboard.server.transport.lwm2m.server.downlink.AbstractTbLwM2MTargetedDownlinkRequest;
public class TbLwM2MWriteCompositeRequest extends AbstractTbLwM2MTargetedDownlinkRequest {
@@ -37,8 +37,8 @@ public class TbLwM2MWriteCompositeRequest extends AbstractTbLwM2MTargetedDownlin
}
@Override
- public LwM2mOperationType getType() {
- return LwM2mOperationType.WRITE_REPLACE;
+ public LwM2MOperationType getType() {
+ return LwM2MOperationType.WRITE_REPLACE;
}
diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/composite/TbLwM2MWriteResponseCompositeCallback.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/composite/TbLwM2MWriteResponseCompositeCallback.java
index 9dccc98185..6d5de06e90 100644
--- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/composite/TbLwM2MWriteResponseCompositeCallback.java
+++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/composite/TbLwM2MWriteResponseCompositeCallback.java
@@ -31,7 +31,7 @@ public class TbLwM2MWriteResponseCompositeCallback extends TbLwM2MUplinkTargeted
@Override
public void onSuccess(WriteCompositeRequest request, WriteCompositeResponse response) {
super.onSuccess(request, response);
- handler.onWriteCompositeResponseOk(client, request);
+ handler.onWriteCompositeResponseOk(client, request, response.getCode().getCode());
}
}
diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/log/DefaultLwM2MTelemetryLogService.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/log/DefaultLwM2MTelemetryLogService.java
index eb5dae8f4a..214c7c2d5e 100644
--- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/log/DefaultLwM2MTelemetryLogService.java
+++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/log/DefaultLwM2MTelemetryLogService.java
@@ -21,9 +21,8 @@ import org.springframework.stereotype.Service;
import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;
import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportServerHelper;
import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
-import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext;
-import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LWM2M_TELEMETRY;
+import static org.thingsboard.server.transport.lwm2m.utils.LwM2MTransportUtil.LOG_LWM2M_TELEMETRY;
@Slf4j
@Service
diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/model/LwM2MModelConfig.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/model/LwM2MModelConfig.java
new file mode 100644
index 0000000000..ba6f8bd5fb
--- /dev/null
+++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/model/LwM2MModelConfig.java
@@ -0,0 +1,92 @@
+/**
+ * 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.model;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.ToString;
+import lombok.extern.slf4j.Slf4j;
+import org.thingsboard.server.common.data.device.profile.lwm2m.ObjectAttributes;
+
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import static org.thingsboard.common.util.CollectionsUtil.diffSets;
+
+@Data
+@NoArgsConstructor
+@ToString(exclude = "toCancelRead")
+@Slf4j
+public class LwM2MModelConfig {
+ private String endpoint;
+ private Map attributesToAdd;
+ private Set attributesToRemove;
+ private Set toObserve;
+ private Set toCancelObserve;
+ private Set toRead;
+ @JsonIgnore
+ private Set toCancelRead;
+
+ public LwM2MModelConfig(String endpoint) {
+ this.endpoint = endpoint;
+ this.attributesToAdd = new ConcurrentHashMap<>();
+ this.attributesToRemove = ConcurrentHashMap.newKeySet();
+ this.toObserve = ConcurrentHashMap.newKeySet();
+ this.toCancelObserve = ConcurrentHashMap.newKeySet();
+ this.toRead = ConcurrentHashMap.newKeySet();
+ this.toCancelRead = new HashSet<>();
+ }
+
+ public void merge(LwM2MModelConfig modelConfig) {
+ if (modelConfig.isEmpty() && modelConfig.getToCancelRead().isEmpty()) {
+ return;
+ }
+
+ modelConfig.getAttributesToAdd().forEach((k, v) -> {
+ if (this.attributesToRemove.contains(k)) {
+ this.attributesToRemove.remove(k);
+ } else {
+ this.attributesToAdd.put(k, v);
+ }
+ });
+
+ modelConfig.getAttributesToRemove().forEach(k -> {
+ if (this.attributesToAdd.containsKey(k)) {
+ this.attributesToRemove.remove(k);
+ } else {
+ this.attributesToRemove.add(k);
+ }
+ });
+
+ this.toObserve.addAll(diffSets(this.toCancelObserve, modelConfig.getToObserve()));
+ this.toCancelObserve.addAll(diffSets(this.toObserve, modelConfig.getToCancelObserve()));
+
+ this.toObserve.removeAll(modelConfig.getToCancelObserve());
+ this.toCancelObserve.removeAll(modelConfig.getToObserve());
+
+ this.toRead.removeAll(modelConfig.getToObserve());
+ this.toRead.removeAll(modelConfig.getToCancelRead());
+ this.toRead.addAll(modelConfig.getToRead());
+ }
+
+ @JsonIgnore
+ public boolean isEmpty() {
+ return attributesToAdd.isEmpty() && toObserve.isEmpty() && toCancelObserve.isEmpty() && toRead.isEmpty();
+ }
+}
diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/model/LwM2MModelConfigService.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/model/LwM2MModelConfigService.java
new file mode 100644
index 0000000000..9670b7791b
--- /dev/null
+++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/model/LwM2MModelConfigService.java
@@ -0,0 +1,29 @@
+/**
+ * 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.model;
+
+import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
+
+public interface LwM2MModelConfigService {
+
+ void sendUpdates(LwM2mClient lwM2mClient);
+
+ void sendUpdates(LwM2mClient lwM2mClient, LwM2MModelConfig modelConfig);
+
+ void persistUpdates(String endpoint);
+
+ void removeUpdates(String endpoint);
+}
diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/model/LwM2MModelConfigServiceImpl.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/model/LwM2MModelConfigServiceImpl.java
new file mode 100644
index 0000000000..fd84b52af0
--- /dev/null
+++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/model/LwM2MModelConfigServiceImpl.java
@@ -0,0 +1,235 @@
+/**
+ * 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.model;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.stereotype.Service;
+import org.thingsboard.server.common.data.device.profile.lwm2m.ObjectAttributes;
+import org.thingsboard.server.queue.util.AfterStartUp;
+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.downlink.DownlinkRequestCallback;
+import org.thingsboard.server.transport.lwm2m.server.downlink.LwM2mDownlinkMsgHandler;
+import org.thingsboard.server.transport.lwm2m.server.downlink.TbLwM2MCancelObserveCallback;
+import org.thingsboard.server.transport.lwm2m.server.downlink.TbLwM2MCancelObserveRequest;
+import org.thingsboard.server.transport.lwm2m.server.downlink.TbLwM2MObserveCallback;
+import org.thingsboard.server.transport.lwm2m.server.downlink.TbLwM2MObserveRequest;
+import org.thingsboard.server.transport.lwm2m.server.downlink.TbLwM2MReadCallback;
+import org.thingsboard.server.transport.lwm2m.server.downlink.TbLwM2MReadRequest;
+import org.thingsboard.server.transport.lwm2m.server.downlink.TbLwM2MWriteAttributesCallback;
+import org.thingsboard.server.transport.lwm2m.server.downlink.TbLwM2MWriteAttributesRequest;
+import org.thingsboard.server.transport.lwm2m.server.log.LwM2MTelemetryLogService;
+import org.thingsboard.server.transport.lwm2m.server.store.TbLwM2MModelConfigStore;
+import org.thingsboard.server.transport.lwm2m.server.uplink.LwM2mUplinkMsgHandler;
+
+import javax.annotation.PreDestroy;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.TimeoutException;
+import java.util.stream.Collectors;
+
+@Slf4j
+@Service
+@TbLwM2mTransportComponent
+public class LwM2MModelConfigServiceImpl implements LwM2MModelConfigService {
+
+ @Autowired
+ private TbLwM2MModelConfigStore modelStore;
+
+ @Autowired
+ @Lazy
+ private LwM2mDownlinkMsgHandler downlinkMsgHandler;
+ @Autowired
+ @Lazy
+ private LwM2mUplinkMsgHandler uplinkMsgHandler;
+ @Autowired
+ @Lazy
+ private LwM2mClientContext clientContext;
+
+ @Autowired
+ private LwM2MTelemetryLogService logService;
+
+ private ConcurrentMap currentModelConfigs;
+
+ @AfterStartUp(order = Integer.MAX_VALUE - 1)
+ private void init() {
+ List models = modelStore.getAll();
+ log.debug("Fetched model configs: {}", models);
+ currentModelConfigs = models.stream()
+ .collect(Collectors.toConcurrentMap(LwM2MModelConfig::getEndpoint, m -> m));
+ }
+
+ @Override
+ public void sendUpdates(LwM2mClient lwM2mClient) {
+ LwM2MModelConfig modelConfig = currentModelConfigs.get(lwM2mClient.getEndpoint());
+ if (modelConfig == null || modelConfig.isEmpty()) {
+ return;
+ }
+
+ doSend(lwM2mClient, modelConfig);
+ }
+
+ public void sendUpdates(LwM2mClient lwM2mClient, LwM2MModelConfig newModelConfig) {
+ String endpoint = lwM2mClient.getEndpoint();
+ LwM2MModelConfig modelConfig = currentModelConfigs.get(endpoint);
+ if (modelConfig == null || modelConfig.isEmpty()) {
+ modelConfig = newModelConfig;
+ currentModelConfigs.put(endpoint, modelConfig);
+ } else {
+ modelConfig.merge(newModelConfig);
+ }
+
+ if (lwM2mClient.isAsleep()) {
+ modelStore.put(modelConfig);
+ } else {
+ doSend(lwM2mClient, modelConfig);
+ }
+ }
+
+ private void doSend(LwM2mClient lwM2mClient, LwM2MModelConfig modelConfig) {
+ log.trace("Send LwM2M Model updates: [{}]", modelConfig);
+
+ String endpoint = lwM2mClient.getEndpoint();
+
+ Map attrToAdd = modelConfig.getAttributesToAdd();
+ attrToAdd.forEach((id, attributes) -> {
+ TbLwM2MWriteAttributesRequest request = TbLwM2MWriteAttributesRequest.builder().versionedId(id)
+ .attributes(attributes)
+ .timeout(clientContext.getRequestTimeout(lwM2mClient)).build();
+ downlinkMsgHandler.sendWriteAttributesRequest(lwM2mClient, request,
+ createDownlinkProxyCallback(() -> {
+ attrToAdd.remove(id);
+ if (modelConfig.isEmpty()) {
+ modelStore.remove(endpoint);
+ }
+ }, new TbLwM2MWriteAttributesCallback(logService, lwM2mClient, id))
+ );
+ });
+
+ Set attrToRemove = modelConfig.getAttributesToRemove();
+ attrToRemove.forEach((id) -> {
+ TbLwM2MWriteAttributesRequest request = TbLwM2MWriteAttributesRequest.builder().versionedId(id)
+ .attributes(new ObjectAttributes())
+ .timeout(clientContext.getRequestTimeout(lwM2mClient)).build();
+ downlinkMsgHandler.sendWriteAttributesRequest(lwM2mClient, request,
+ createDownlinkProxyCallback(() -> {
+ attrToRemove.remove(id);
+ if (modelConfig.isEmpty()) {
+ modelStore.remove(endpoint);
+ }
+ }, new TbLwM2MWriteAttributesCallback(logService, lwM2mClient, id))
+ );
+ });
+
+ Set toRead = modelConfig.getToRead();
+ toRead.forEach(id -> {
+ TbLwM2MReadRequest request = TbLwM2MReadRequest.builder().versionedId(id)
+ .timeout(clientContext.getRequestTimeout(lwM2mClient)).build();
+ downlinkMsgHandler.sendReadRequest(lwM2mClient, request,
+ createDownlinkProxyCallback(() -> {
+ toRead.remove(id);
+ if (modelConfig.isEmpty()) {
+ modelStore.remove(endpoint);
+ }
+ }, new TbLwM2MReadCallback(uplinkMsgHandler, logService, lwM2mClient, id))
+ );
+ });
+
+ Set toObserve = modelConfig.getToObserve();
+ toObserve.forEach(id -> {
+ TbLwM2MObserveRequest request = TbLwM2MObserveRequest.builder().versionedId(id)
+ .timeout(clientContext.getRequestTimeout(lwM2mClient)).build();
+ downlinkMsgHandler.sendObserveRequest(lwM2mClient, request,
+ createDownlinkProxyCallback(() -> {
+ toObserve.remove(id);
+ if (modelConfig.isEmpty()) {
+ modelStore.remove(endpoint);
+ }
+ }, new TbLwM2MObserveCallback(uplinkMsgHandler, logService, lwM2mClient, id))
+ );
+ });
+
+ Set toCancelObserve = modelConfig.getToCancelObserve();
+ toCancelObserve.forEach(id -> {
+ TbLwM2MCancelObserveRequest request = TbLwM2MCancelObserveRequest.builder().versionedId(id)
+ .timeout(clientContext.getRequestTimeout(lwM2mClient)).build();
+ downlinkMsgHandler.sendCancelObserveRequest(lwM2mClient, request,
+ createDownlinkProxyCallback(() -> {
+ toCancelObserve.remove(id);
+ if (modelConfig.isEmpty()) {
+ modelStore.remove(endpoint);
+ }
+ }, new TbLwM2MCancelObserveCallback(logService, lwM2mClient, id))
+ );
+ });
+ }
+
+ private DownlinkRequestCallback createDownlinkProxyCallback(Runnable processRemove, DownlinkRequestCallback callback) {
+ return new DownlinkRequestCallback<>() {
+ @Override
+ public void onSuccess(R request, T response) {
+ processRemove.run();
+ callback.onSuccess(request, response);
+ }
+
+ @Override
+ public void onValidationError(String params, String msg) {
+ processRemove.run();
+ callback.onValidationError(params, msg);
+ }
+
+ @Override
+ public void onError(String params, Exception e) {
+ try {
+ if (e instanceof TimeoutException) {
+ return;
+ }
+ processRemove.run();
+ } finally {
+ callback.onError(params, e);
+ }
+ }
+
+ };
+ }
+
+ @Override
+ public void persistUpdates(String endpoint) {
+ LwM2MModelConfig modelConfig = currentModelConfigs.get(endpoint);
+ if (modelConfig != null && !modelConfig.isEmpty()) {
+ modelStore.put(modelConfig);
+ }
+ }
+
+ @Override
+ public void removeUpdates(String endpoint) {
+ currentModelConfigs.remove(endpoint);
+ }
+
+ @PreDestroy
+ private void destroy() {
+ currentModelConfigs.values().forEach(model -> {
+ if (model != null && !model.isEmpty()) {
+ modelStore.put(model);
+ }
+ });
+ }
+}
diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/DefaultLwM2MOtaUpdateService.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/DefaultLwM2MOtaUpdateService.java
index 2776b64fef..e52cdc9956 100644
--- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/DefaultLwM2MOtaUpdateService.java
+++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/DefaultLwM2MOtaUpdateService.java
@@ -25,7 +25,7 @@ import org.springframework.stereotype.Service;
import org.thingsboard.common.util.DonAsynchron;
import org.thingsboard.server.cache.ota.OtaPackageDataCache;
import org.thingsboard.server.common.data.StringUtils;
-import org.thingsboard.server.common.data.device.data.lwm2m.OtherConfiguration;
+import org.thingsboard.server.common.data.device.profile.lwm2m.OtherConfiguration;
import org.thingsboard.server.common.data.ota.OtaPackageKey;
import org.thingsboard.server.common.data.ota.OtaPackageType;
import org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus;
@@ -74,8 +74,10 @@ import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.UPDA
import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.UPDATING;
import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.VERIFIED;
import static org.thingsboard.server.common.data.ota.OtaPackageUtil.getAttributeKey;
-import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LWM2M_TELEMETRY;
-import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertObjectIdToVersionedId;
+import static org.thingsboard.server.transport.lwm2m.server.ota.firmware.FirmwareUpdateResult.UPDATE_SUCCESSFULLY;
+import static org.thingsboard.server.transport.lwm2m.server.ota.software.SoftwareUpdateResult.NOT_ENOUGH_STORAGE;
+import static org.thingsboard.server.transport.lwm2m.utils.LwM2MTransportUtil.LOG_LWM2M_TELEMETRY;
+import static org.thingsboard.server.transport.lwm2m.utils.LwM2MTransportUtil.convertObjectIdToVersionedId;
@Slf4j
@Service
@@ -180,9 +182,8 @@ public class DefaultLwM2MOtaUpdateService extends LwM2MExecutorAwareService impl
}
var clientSettings = clientContext.getProfile(client.getProfileId()).getClientLwM2mSettings();
-
- onFirmwareStrategyUpdate(client, clientSettings);
- onCurrentSoftwareStrategyUpdate(client, clientSettings);
+ initFwStrategy(client, clientSettings);
+ initSwStrategy(client, clientSettings);
if (!attributesToFetch.isEmpty()) {
var future = attributesService.getSharedAttributes(client, attributesToFetch);
@@ -192,7 +193,7 @@ public class DefaultLwM2MOtaUpdateService extends LwM2MExecutorAwareService impl
Optional newFwVersion = getAttributeValue(attrs, FIRMWARE_VERSION);
Optional newFwTag = getAttributeValue(attrs, FIRMWARE_TAG);
Optional newFwUrl = getAttributeValue(attrs, FIRMWARE_URL);
- if (newFwTitle.isPresent() && newFwVersion.isPresent()) {
+ if (newFwTitle.isPresent() && newFwVersion.isPresent() && !isOtaDownloading(client) && !UPDATING.equals(fwInfo.status)) {
onTargetFirmwareUpdate(client, newFwTitle.get(), newFwVersion.get(), newFwUrl, newFwTag);
}
}
@@ -244,19 +245,27 @@ public class DefaultLwM2MOtaUpdateService extends LwM2MExecutorAwareService impl
@Override
public void onFirmwareStrategyUpdate(LwM2mClient client, OtherConfiguration configuration) {
log.debug("[{}] Current fw strategy: {}", client.getEndpoint(), configuration.getFwUpdateStrategy());
+ startFirmwareUpdateIfNeeded(client, initFwStrategy(client, configuration));
+ }
+
+ private LwM2MClientFwOtaInfo initFwStrategy(LwM2mClient client, OtherConfiguration configuration) {
LwM2MClientFwOtaInfo fwInfo = getOrInitFwInfo(client);
fwInfo.setStrategy(LwM2MFirmwareUpdateStrategy.fromStrategyFwByCode(configuration.getFwUpdateStrategy()));
fwInfo.setBaseUrl(configuration.getFwUpdateResource());
- startFirmwareUpdateIfNeeded(client, fwInfo);
+ return fwInfo;
}
@Override
public void onCurrentSoftwareStrategyUpdate(LwM2mClient client, OtherConfiguration configuration) {
log.debug("[{}] Current sw strategy: {}", client.getEndpoint(), configuration.getSwUpdateStrategy());
+ startSoftwareUpdateIfNeeded(client, initSwStrategy(client, configuration));
+ }
+
+ private LwM2MClientSwOtaInfo initSwStrategy(LwM2mClient client, OtherConfiguration configuration) {
LwM2MClientSwOtaInfo swInfo = getOrInitSwInfo(client);
swInfo.setStrategy(LwM2MSoftwareUpdateStrategy.fromStrategySwByCode(configuration.getSwUpdateStrategy()));
swInfo.setBaseUrl(configuration.getSwUpdateResource());
- startSoftwareUpdateIfNeeded(client, swInfo);
+ return swInfo;
}
@Override
@@ -307,6 +316,7 @@ public class DefaultLwM2MOtaUpdateService extends LwM2MExecutorAwareService impl
if (FirmwareUpdateResult.INITIAL.equals(result) && OtaPackageUpdateStatus.UPDATING.equals(fwInfo.getStatus())) {
status = Optional.of(UPDATED);
fwInfo.setRetryAttempts(0);
+ fwInfo.setFailedPackageId(null);
}
status.ifPresent(otaStatus -> {
@@ -387,6 +397,22 @@ public class DefaultLwM2MOtaUpdateService extends LwM2MExecutorAwareService impl
startSoftwareUpdateIfNeeded(client, fwInfo);
}
+ @Override
+ public boolean isOtaDownloading(LwM2mClient client) {
+ String endpoint = client.getEndpoint();
+ LwM2MClientFwOtaInfo fwInfo = fwStates.get(endpoint);
+ LwM2MClientSwOtaInfo swInfo = swStates.get(endpoint);
+
+ if (fwInfo != null && (DOWNLOADING.equals(fwInfo.getStatus()))) {
+ return true;
+ }
+ if (swInfo != null && (DOWNLOADING.equals(swInfo.getStatus()))) {
+ return true;
+ }
+
+ return false;
+ }
+
private void startFirmwareUpdateIfNeeded(LwM2mClient client, LwM2MClientFwOtaInfo fwInfo) {
try {
if (!fwInfo.isSupported() && fwInfo.isAssigned()) {
@@ -400,9 +426,12 @@ public class DefaultLwM2MOtaUpdateService extends LwM2MExecutorAwareService impl
log.debug("[{}] Starting update to [{}{}] using binary", client.getEndpoint(), fwInfo.getTargetName(), fwInfo.getTargetVersion());
startUpdateUsingBinary(client, fwInfo);
}
+ } else if (fwInfo.getResult() != null && fwInfo.getResult().getCode() > UPDATE_SUCCESSFULLY.getCode()) {
+ log.trace("[{}] Previous update failed. [{}]", client.getEndpoint(), fwInfo);
+ logService.log(client, "Previous update firmware failed. Result: " + fwInfo.getResult().name());
}
} catch (Exception e) {
- log.info("[{}] failed to update client: {}", client.getEndpoint(), fwInfo, e);
+ log.error("[{}] failed to update client: {}", client.getEndpoint(), fwInfo, e);
sendStateUpdateToTelemetry(client, fwInfo, OtaPackageUpdateStatus.FAILED, "Internal server error: " + e.getMessage());
}
}
@@ -425,6 +454,9 @@ public class DefaultLwM2MOtaUpdateService extends LwM2MExecutorAwareService impl
startUpdateUsingBinary(client, swInfo);
}
}
+ } else if (swInfo.getResult() != null && swInfo.getResult().getCode() >= NOT_ENOUGH_STORAGE.getCode()) {
+ log.trace("[{}] Previous update failed. [{}]", client.getEndpoint(), swInfo);
+ logService.log(client, "Previous update software failed. Result: " + swInfo.getResult().name());
}
} catch (Exception e) {
log.info("[{}] failed to update client: {}", client.getEndpoint(), swInfo, e);
diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/LwM2MOtaUpdateService.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/LwM2MOtaUpdateService.java
index b03fe81d28..4aa3776682 100644
--- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/LwM2MOtaUpdateService.java
+++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/LwM2MOtaUpdateService.java
@@ -15,7 +15,7 @@
*/
package org.thingsboard.server.transport.lwm2m.server.ota;
-import org.thingsboard.server.common.data.device.data.lwm2m.OtherConfiguration;
+import org.thingsboard.server.common.data.device.profile.lwm2m.OtherConfiguration;
import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
import java.util.Optional;
@@ -55,4 +55,6 @@ public interface LwM2MOtaUpdateService {
void onCurrentSoftwareStateUpdate(LwM2mClient lwM2MClient, Long value);
void onCurrentSoftwareResultUpdate(LwM2mClient client, Long result);
+
+ boolean isOtaDownloading(LwM2mClient client);
}
diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/firmware/FirmwareUpdateState.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/firmware/FirmwareUpdateState.java
index ddd04fbfd0..9d3c0b06f0 100644
--- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/firmware/FirmwareUpdateState.java
+++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/firmware/FirmwareUpdateState.java
@@ -15,6 +15,8 @@
*/
package org.thingsboard.server.transport.lwm2m.server.ota.firmware;
+import lombok.Getter;
+
/**
* /** State R
* 0: Idle (before downloading or after successful updating)
@@ -28,8 +30,10 @@ public enum FirmwareUpdateState {
DOWNLOADED(2, "Downloaded"),
UPDATING(3, "Updating");
- public int code;
- public String type;
+ @Getter
+ private int code;
+ @Getter
+ private String type;
FirmwareUpdateState(int code, String type) {
this.code = code;
diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/software/LwM2MClientSwOtaInfo.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/software/LwM2MClientSwOtaInfo.java
index 547d713251..e4b8336f92 100644
--- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/software/LwM2MClientSwOtaInfo.java
+++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/software/LwM2MClientSwOtaInfo.java
@@ -20,12 +20,8 @@ import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.ToString;
-import org.thingsboard.server.common.data.StringUtils;
import org.thingsboard.server.common.data.ota.OtaPackageType;
import org.thingsboard.server.transport.lwm2m.server.ota.LwM2MClientOtaInfo;
-import org.thingsboard.server.transport.lwm2m.server.ota.firmware.FirmwareUpdateResult;
-import org.thingsboard.server.transport.lwm2m.server.ota.firmware.FirmwareUpdateState;
-import org.thingsboard.server.transport.lwm2m.server.ota.firmware.LwM2MFirmwareUpdateStrategy;
@Data
@EqualsAndHashCode(callSuper = true)
diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/software/SoftwareUpdateResult.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/software/SoftwareUpdateResult.java
index 7bf5473a1b..6ceb263db5 100644
--- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/software/SoftwareUpdateResult.java
+++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/software/SoftwareUpdateResult.java
@@ -56,10 +56,12 @@ public enum SoftwareUpdateResult {
INSTALL_FAILURE(58, "Software installation failure", true),
UN_INSTALL_FAILURE(59, "Uninstallation Failure during forUpdate(arg=0)", true);
- public int code;
- public String type;
@Getter
- public boolean isAgain;
+ private int code;
+ @Getter
+ private String type;
+ @Getter
+ private boolean isAgain;
SoftwareUpdateResult(int code, String type, boolean isAgain) {
this.code = code;
diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/software/SoftwareUpdateState.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/software/SoftwareUpdateState.java
index 394d2e501a..c2e954f556 100644
--- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/software/SoftwareUpdateState.java
+++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/software/SoftwareUpdateState.java
@@ -15,6 +15,8 @@
*/
package org.thingsboard.server.transport.lwm2m.server.ota.software;
+import lombok.Getter;
+
/**
* SW Update State R
* 0: INITIAL Before downloading. (see 5.1.2.1)
@@ -33,8 +35,10 @@ public enum SoftwareUpdateState {
DELIVERED(3, "Delivered"),
INSTALLED(4, "Installed");
- public int code;
- public String type;
+ @Getter
+ private int code;
+ @Getter
+ private String type;
SoftwareUpdateState(int code, String type) {
this.code = code;
diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/rpc/DefaultLwM2MRpcRequestHandler.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/rpc/DefaultLwM2MRpcRequestHandler.java
index a728a0b6e0..9aae838cdb 100644
--- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/rpc/DefaultLwM2MRpcRequestHandler.java
+++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/rpc/DefaultLwM2MRpcRequestHandler.java
@@ -15,18 +15,25 @@
*/
package org.thingsboard.server.transport.lwm2m.server.rpc;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonSyntaxException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.eclipse.leshan.core.ResponseCode;
+import org.eclipse.leshan.core.model.ResourceModel;
+import org.eclipse.leshan.core.node.LwM2mPath;
+import org.eclipse.leshan.core.request.ContentFormat;
+import org.eclipse.leshan.server.model.LwM2mModelProvider;
import org.springframework.stereotype.Service;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.common.data.StringUtils;
import org.thingsboard.server.common.transport.TransportService;
+import org.thingsboard.server.common.transport.util.JsonUtils;
import org.thingsboard.server.gen.transport.TransportProtos;
import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;
import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig;
-import org.thingsboard.server.transport.lwm2m.server.LwM2mOperationType;
+import org.thingsboard.server.transport.lwm2m.server.LwM2MOperationType;
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.downlink.LwM2mDownlinkMsgHandler;
@@ -34,6 +41,8 @@ import org.thingsboard.server.transport.lwm2m.server.downlink.TbLwM2MCancelAllOb
import org.thingsboard.server.transport.lwm2m.server.downlink.TbLwM2MCancelAllRequest;
import org.thingsboard.server.transport.lwm2m.server.downlink.TbLwM2MCancelObserveCallback;
import org.thingsboard.server.transport.lwm2m.server.downlink.TbLwM2MCancelObserveRequest;
+import org.thingsboard.server.transport.lwm2m.server.downlink.TbLwM2MCreateRequest;
+import org.thingsboard.server.transport.lwm2m.server.downlink.TbLwM2MCreateResponseCallback;
import org.thingsboard.server.transport.lwm2m.server.downlink.TbLwM2MDeleteCallback;
import org.thingsboard.server.transport.lwm2m.server.downlink.TbLwM2MDeleteRequest;
import org.thingsboard.server.transport.lwm2m.server.downlink.TbLwM2MDiscoverAllRequest;
@@ -60,10 +69,15 @@ import org.thingsboard.server.transport.lwm2m.server.rpc.composite.RpcReadRespon
import org.thingsboard.server.transport.lwm2m.server.rpc.composite.RpcWriteCompositeRequest;
import org.thingsboard.server.transport.lwm2m.server.uplink.LwM2mUplinkMsgHandler;
+import java.util.LinkedHashMap;
+import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
+import static org.thingsboard.server.transport.lwm2m.utils.LwM2MTransportUtil.convertMultiResourceValuesFromRpcBody;
+import static org.thingsboard.server.transport.lwm2m.utils.LwM2MTransportUtil.fromVersionedIdToObjectId;
+
@Slf4j
@Service
@TbLwM2mTransportComponent
@@ -72,16 +86,16 @@ public class DefaultLwM2MRpcRequestHandler implements LwM2MRpcRequestHandler {
private final TransportService transportService;
private final LwM2mClientContext clientContext;
- private final LwM2MTransportServerConfig config;
private final LwM2mUplinkMsgHandler uplinkHandler;
private final LwM2mDownlinkMsgHandler downlinkHandler;
private final LwM2MTelemetryLogService logService;
+ private final LwM2mModelProvider modelProvider;
@Override
public void onToDeviceRpcRequest(TransportProtos.ToDeviceRpcRequestMsg rpcRequest, TransportProtos.SessionInfoProto sessionInfo) {
log.debug("Received params: {}", rpcRequest.getParams());
try {
- LwM2mOperationType operationType = LwM2mOperationType.fromType(rpcRequest.getMethodName());
+ LwM2MOperationType operationType = LwM2MOperationType.fromType(rpcRequest.getMethodName());
if (operationType == null) {
this.sendErrorRpcResponse(sessionInfo, rpcRequest.getRequestId(), ResponseCode.METHOD_NOT_ALLOWED, "Unsupported operation type: " + rpcRequest.getMethodName());
return;
@@ -105,7 +119,8 @@ public class DefaultLwM2MRpcRequestHandler implements LwM2MRpcRequestHandler {
}
try {
if (operationType.isHasObjectId()) {
- String objectId = getIdFromParameters(client, rpcRequest);
+ LwM2MRpcRequestHeader header = JacksonUtil.fromString(rpcRequest.getParams(), LwM2MRpcRequestHeader.class);
+ String objectId = getIdFromParameters(client, header);
switch (operationType) {
case READ:
sendReadRequest(client, rpcRequest, objectId);
@@ -134,17 +149,21 @@ public class DefaultLwM2MRpcRequestHandler implements LwM2MRpcRequestHandler {
case WRITE_REPLACE:
sendWriteReplaceRequest(client, rpcRequest, objectId);
break;
+ case CREATE:
+ sendCreateRequest(client, rpcRequest, objectId);
+ break;
default:
throw new IllegalArgumentException("Unsupported operation: " + operationType.name());
}
} else if (operationType.isComposite()) {
- if (clientContext.isComposite(client)) {
+ ContentFormat contentFormatComposite = this.getCompositeContentFormat(client);
+ if (contentFormatComposite != null) {
switch (operationType) {
case READ_COMPOSITE:
- sendReadCompositeRequest(client, rpcRequest);
+ sendReadCompositeRequest(client, rpcRequest, contentFormatComposite);
break;
case WRITE_COMPOSITE:
- sendWriteCompositeRequest(client, rpcRequest);
+ sendWriteCompositeRequest(client, rpcRequest, contentFormatComposite);
break;
default:
throw new IllegalArgumentException("Unsupported operation: " + operationType.name());
@@ -164,8 +183,6 @@ public class DefaultLwM2MRpcRequestHandler implements LwM2MRpcRequestHandler {
case DISCOVER_ALL:
sendDiscoverAllRequest(client, rpcRequest);
break;
- case FW_UPDATE:
- //TODO: implement and add break statement
default:
throw new IllegalArgumentException("Unsupported operation: " + operationType.name());
}
@@ -186,12 +203,12 @@ public class DefaultLwM2MRpcRequestHandler implements LwM2MRpcRequestHandler {
downlinkHandler.sendReadRequest(client, request, rpcCallback);
}
- private void sendReadCompositeRequest(LwM2mClient client, TransportProtos.ToDeviceRpcRequestMsg requestMsg) {
+ private void sendReadCompositeRequest(LwM2mClient client, TransportProtos.ToDeviceRpcRequestMsg requestMsg, ContentFormat contentFormatComposite) {
String[] versionedIds = getIdsFromParameters(client, requestMsg);
TbLwM2MReadCompositeRequest request = TbLwM2MReadCompositeRequest.builder().versionedIds(versionedIds).timeout(clientContext.getRequestTimeout(client)).build();
var mainCallback = new TbLwM2MReadCompositeCallback(uplinkHandler, logService, client, versionedIds);
- var rpcCallback = new RpcReadResponseCompositeCallback<>(transportService, client, requestMsg, mainCallback);
- downlinkHandler.sendReadCompositeRequest(client, request, rpcCallback);
+ var rpcCallback = new RpcReadResponseCompositeCallback(transportService, client, requestMsg, mainCallback);
+ downlinkHandler.sendReadCompositeRequest(client, request, rpcCallback, contentFormatComposite);
}
private void sendObserveRequest(LwM2mClient client, TransportProtos.ToDeviceRpcRequestMsg requestMsg, String versionedId) {
@@ -244,8 +261,28 @@ public class DefaultLwM2MRpcRequestHandler implements LwM2MRpcRequestHandler {
downlinkHandler.sendWriteUpdateRequest(client, builder.build(), rpcCallback);
}
+ private void sendCreateRequest(LwM2mClient client, TransportProtos.ToDeviceRpcRequestMsg requestMsg, String versionedId) {
+ RpcCreateRequest requestBody = JacksonUtil.fromString(requestMsg.getParams(), RpcCreateRequest.class);
+ TbLwM2MCreateRequest.TbLwM2MCreateRequestBuilder builder = TbLwM2MCreateRequest.builder().versionedId(versionedId);
+ builder.value(requestBody.getValue()).nodes(requestBody.getNodes()).timeout(clientContext.getRequestTimeout(client));
+ var mainCallback = new TbLwM2MCreateResponseCallback(uplinkHandler, logService, client, versionedId);
+ var rpcCallback = new RpcCreateResponseCallback<>(transportService, client, requestMsg, mainCallback);
+ downlinkHandler.sendCreateRequest(client, builder.build(), rpcCallback);
+ }
+
private void sendWriteReplaceRequest(LwM2mClient client, TransportProtos.ToDeviceRpcRequestMsg requestMsg, String versionedId) {
RpcWriteReplaceRequest requestBody = JacksonUtil.fromString(requestMsg.getParams(), RpcWriteReplaceRequest.class);
+ LwM2mPath path = new LwM2mPath(fromVersionedIdToObjectId(versionedId));
+ if (path.isResource()) {
+ ResourceModel resourceModel = client.getResourceModel(versionedId, modelProvider);
+ if (resourceModel != null && resourceModel.multiple) {
+ try {
+ Map value = convertMultiResourceValuesFromRpcBody(requestBody.getValue(), resourceModel.type, versionedId);
+ requestBody.setValue(value);
+ } catch (Exception e) {
+ }
+ }
+ }
TbLwM2MWriteReplaceRequest request = TbLwM2MWriteReplaceRequest.builder().versionedId(versionedId)
.value(requestBody.getValue())
.timeout(clientContext.getRequestTimeout(client)).build();
@@ -262,11 +299,52 @@ public class DefaultLwM2MRpcRequestHandler implements LwM2MRpcRequestHandler {
* nodes.put("/1/0/2", 100);
* nodes.put("/5/0/1", "coap://localhost:5685");
*/
- private void sendWriteCompositeRequest(LwM2mClient client, TransportProtos.ToDeviceRpcRequestMsg requestMsg) {
+ private void sendWriteCompositeRequest(LwM2mClient client, TransportProtos.ToDeviceRpcRequestMsg requestMsg, ContentFormat contentFormatComposite) {
RpcWriteCompositeRequest rpcWriteCompositeRequest = JacksonUtil.fromString(requestMsg.getParams(), RpcWriteCompositeRequest.class);
- var mainCallback = new TbLwM2MWriteResponseCompositeCallback(uplinkHandler, logService, client, null);
- var rpcCallback = new RpcEmptyResponseCallback<>(transportService, client, requestMsg, mainCallback);
- downlinkHandler.sendWriteCompositeRequest(client, rpcWriteCompositeRequest, rpcCallback);
+ Map validNodes = validateNodes(client, rpcWriteCompositeRequest.getNodes());
+ if (validNodes.size() > 0) {
+ rpcWriteCompositeRequest.setNodes(validNodes);
+ var mainCallback = new TbLwM2MWriteResponseCompositeCallback(uplinkHandler, logService, client, null);
+ var rpcCallback = new RpcEmptyResponseCallback<>(transportService, client, requestMsg, mainCallback);
+ downlinkHandler.sendWriteCompositeRequest(client, rpcWriteCompositeRequest, rpcCallback, contentFormatComposite);
+ } else {
+ throw new IllegalArgumentException(String.format("nodes: %s is not validate value", rpcWriteCompositeRequest.getNodes().toString()));
+ }
+ }
+
+ private Map validateNodes(LwM2mClient client, Map nodes) {
+ Map