Browse Source

Lwm2m: opaque

pull/4834/head
nickAS21 5 years ago
parent
commit
3d8f19c23e
  1. 9
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/config/LwM2mVersion.java
  2. 79
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClient.java
  3. 1
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientContextImpl.java
  4. 12
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/ResourceValue.java
  5. 38
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/rpc/DefaultLwM2MRpcRequestHandler.java
  6. 13
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/rpc/RpcReadResponseCallback.java
  7. 3
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/rpc/composite/RpcReadResponseCompositeCallback.java
  8. 12
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/uplink/DefaultLwM2MUplinkMsgHandler.java

9
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/config/LwM2mVersion.java

@ -20,8 +20,8 @@ import org.eclipse.leshan.core.LwM2m.Version;
import org.eclipse.leshan.core.request.ContentFormat; import org.eclipse.leshan.core.request.ContentFormat;
public enum LwM2mVersion { public enum LwM2mVersion {
VERSION_1_0(0, Version.V1_0, ContentFormat.TLV), VERSION_1_0(0, Version.V1_0, ContentFormat.TLV, false),
VERSION_1_1(1, Version.V1_1, ContentFormat.TEXT); VERSION_1_1(1, Version.V1_1, ContentFormat.TEXT, true);
@Getter @Getter
private final int code; private final int code;
@ -29,11 +29,14 @@ public enum LwM2mVersion {
private final Version version; private final Version version;
@Getter @Getter
private final ContentFormat contentFormat; private final ContentFormat contentFormat;
@Getter
private final boolean composite;
LwM2mVersion(int code, Version version, ContentFormat contentFormat) { LwM2mVersion(int code, Version version, ContentFormat contentFormat, boolean composite) {
this.code = code; this.code = code;
this.version = version; this.version = version;
this.contentFormat = contentFormat; this.contentFormat = contentFormat;
this.composite = composite;
} }
public static LwM2mVersion fromVersion(Version version) { public static LwM2mVersion fromVersion(Version version) {

79
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClient.java

@ -20,13 +20,13 @@ import lombok.Setter;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.eclipse.leshan.core.model.ObjectModel; import org.eclipse.leshan.core.model.ObjectModel;
import org.eclipse.leshan.core.model.ResourceModel; import org.eclipse.leshan.core.model.ResourceModel;
import org.eclipse.leshan.core.node.LwM2mObject; import org.eclipse.leshan.core.node.LwM2mMultipleResource;
import org.eclipse.leshan.core.node.LwM2mObjectInstance;
import org.eclipse.leshan.core.node.LwM2mPath; import org.eclipse.leshan.core.node.LwM2mPath;
import org.eclipse.leshan.core.node.LwM2mResource; import org.eclipse.leshan.core.node.LwM2mResource;
import org.eclipse.leshan.core.node.LwM2mSingleResource; import org.eclipse.leshan.core.node.LwM2mSingleResource;
import org.eclipse.leshan.core.node.codec.LwM2mValueConverter; import org.eclipse.leshan.core.node.codec.LwM2mValueConverter;
import org.eclipse.leshan.core.request.ContentFormat; import org.eclipse.leshan.core.request.ContentFormat;
import org.eclipse.leshan.core.util.Hex;
import org.eclipse.leshan.server.model.LwM2mModelProvider; import org.eclipse.leshan.server.model.LwM2mModelProvider;
import org.eclipse.leshan.server.registration.Registration; import org.eclipse.leshan.server.registration.Registration;
import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.Device;
@ -43,6 +43,7 @@ import java.io.IOException;
import java.io.ObjectInputStream; import java.io.ObjectInputStream;
import java.io.Serializable; import java.io.Serializable;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
@ -52,6 +53,7 @@ import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static org.eclipse.leshan.core.model.ResourceModel.Type.OPAQUE;
import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_PATH; import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_PATH;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LWM2M_OBJECT_VERSION_DEFAULT; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LWM2M_OBJECT_VERSION_DEFAULT;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertObjectIdToVersionedId; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertObjectIdToVersionedId;
@ -239,36 +241,71 @@ public class LwM2mClient implements Serializable {
.getObjectModel(pathIds.getObjectId()) : null; .getObjectModel(pathIds.getObjectId()) : null;
} }
public String objectToString(LwM2mObject lwM2mObject) { public Optional<String> contentToString(Object content) {
String value = null;
LwM2mResource resource = null;
String key = null;
if (content instanceof HashMap && ((HashMap) content).size() == 1) {
key = ((HashMap) content).keySet().toArray()[0].toString();
if (((HashMap) content).values().toArray()[0] != null) {
if (((HashMap) content).values().toArray()[0] instanceof LwM2mResource) {
resource = (LwM2mResource) ((HashMap) content).values().toArray()[0];
}
}
} else if (content instanceof LwM2mResource) {
resource = (LwM2mResource) content;
}
if (resource != null && resource.getType() == OPAQUE) {
value = this.resourceToString(resource, key);
}
value = value == null ? content.toString() : value;
return Optional.of(String.format("%s", value));
}
public String resourceToString(LwM2mResource resource, String key) {
String value = null;
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
builder.append("LwM2mObject [id=").append(lwM2mObject.getId()).append(", instances={"); if (resource instanceof LwM2mSingleResource && ((byte[]) resource.getValue()).length > 0) {
lwM2mObject.getInstances().forEach((instId, inst) -> { builder.append("LwM2mSingleResource");
builder.append(instId).append("=").append(this.instanceToString(inst)).append(", "); if (key == null) {
}); builder.append(" id=").append(String.valueOf(resource.getId()));
int startInd = builder.lastIndexOf(", "); } else {
if (startInd > 0) { builder.append(" key=").append(key);
builder.delete(startInd, startInd + 2); }
builder.append(" value=").append(opaqueToString((byte[]) resource.getValue()));
builder.append(" type=").append(OPAQUE.toString());
value = builder.toString();
} else if (resource instanceof LwM2mMultipleResource) {
builder.append("LwM2mMultipleResource");
if (key == null) {
builder.append(" id=").append(String.valueOf(resource.getId()));
} else {
builder.append(" key=").append(key);
}
builder.append(" values={");
builder.append(multiInstanceOpaqueToString((LwM2mMultipleResource) resource));
builder.append("}");
builder.append(" type=").append(OPAQUE.toString());
value = builder.toString();
} }
builder.append("}]"); return value;
return builder.toString();
} }
public String instanceToString(LwM2mObjectInstance objectInstance) { private String multiInstanceOpaqueToString(LwM2mMultipleResource resource) {
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
builder.append("LwM2mObjectInstance [id=").append(objectInstance.getId()).append(", resources={"); resource.getInstances().values().stream().map(v -> {
objectInstance.getResources().forEach((resId, res) -> { return builder.append(" id=").append(v.getId()).append(" value=").append(Hex.encodeHexString((byte[]) v.getValue())).append(", ");
builder.append(resId).append("=").append(this.resourceToString(res)).append(", ");
}); });
int startInd = builder.lastIndexOf(", "); int startInd = builder.lastIndexOf(", ");
if (startInd > 0) { if (startInd > 0) {
builder.delete(startInd, startInd + 2); builder.delete(startInd, startInd + 2);
} }
builder.append("}]");
return builder.toString(); return builder.toString();
} }
public String resourceToString(LwM2mResource lwM2mResource) { private String opaqueToString(byte[] value) {
return lwM2mResource.isMultiInstances() ? lwM2mResource.getInstances().toString() : lwM2mResource.getValue().toString(); String opaque = Hex.encodeHexString(value);
return opaque.length() > 1024 ? opaque.substring(0, 1024) : opaque;
} }
public Collection<LwM2mResource> getNewResourceForInstance(String pathRezIdVer, Object params, LwM2mModelProvider modelProvider, public Collection<LwM2mResource> getNewResourceForInstance(String pathRezIdVer, Object params, LwM2mModelProvider modelProvider,
@ -366,5 +403,9 @@ public class LwM2mClient implements Serializable {
this.lock = new ReentrantLock(); this.lock = new ReentrantLock();
} }
public boolean isComposite (LwM2mClientContext clientContext) {
return LwM2mVersion.fromVersionStr(registration.getLwM2mVersion()).isComposite() &
clientContext.getProfile(this.profileId).getClientLwM2mSettings().isComposite();
}
} }

1
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientContextImpl.java

@ -26,7 +26,6 @@ import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTransportConfiguration; import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTransportConfiguration;
import org.thingsboard.server.common.data.id.DeviceProfileId; import org.thingsboard.server.common.data.id.DeviceProfileId;
import org.thingsboard.server.common.transport.TransportDeviceProfileCache; import org.thingsboard.server.common.transport.TransportDeviceProfileCache;
import org.thingsboard.server.common.transport.TransportService;
import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse; import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse;
import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.gen.transport.TransportProtos;
import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;

12
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/ResourceValue.java

@ -21,6 +21,7 @@ import org.eclipse.leshan.core.node.LwM2mResource;
import org.eclipse.leshan.core.node.LwM2mResourceInstance; import org.eclipse.leshan.core.node.LwM2mResourceInstance;
import java.io.Serializable; import java.io.Serializable;
import java.util.stream.Collectors;
@Data @Data
public class ResourceValue implements Serializable { public class ResourceValue implements Serializable {
@ -45,9 +46,14 @@ public class ResourceValue implements Serializable {
private static TbLwM2MResource toTbLwM2MResource(LwM2mResource lwM2mResource) { private static TbLwM2MResource toTbLwM2MResource(LwM2mResource lwM2mResource) {
if (lwM2mResource.isMultiInstances()) { if (lwM2mResource.isMultiInstances()) {
TbLwM2MResourceInstance[] instances = (TbLwM2MResourceInstance[]) lwM2mResource.getInstances().values().stream().map(ResourceValue::toTbLwM2MResourceInstance).toArray(); if ( lwM2mResource.getInstances().values().size() > 0) {
return new TbLwM2MMultipleResource(lwM2mResource.getId(), lwM2mResource.getType(), instances); TbLwM2MResourceInstance [] instances = lwM2mResource.getInstances().values().stream().map(ResourceValue::toTbLwM2MResourceInstance).collect(Collectors.toSet()).toArray(new TbLwM2MResourceInstance[0]);
} else { return new TbLwM2MMultipleResource(lwM2mResource.getId(), lwM2mResource.getType(), instances);
}
else {
return new TbLwM2MMultipleResource(lwM2mResource.getId(), lwM2mResource.getType(), new TbLwM2MResourceInstance[0]);
}
} else {
return new TbLwM2MSingleResource(lwM2mResource.getId(), lwM2mResource.getValue(), lwM2mResource.getType()); return new TbLwM2MSingleResource(lwM2mResource.getId(), lwM2mResource.getValue(), lwM2mResource.getType());
} }
} }

38
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/rpc/DefaultLwM2MRpcRequestHandler.java

@ -97,7 +97,7 @@ public class DefaultLwM2MRpcRequestHandler implements LwM2MRpcRequestHandler {
return; return;
} }
try { try {
if (operationType.isHasObjectId()) { if (operationType.isHasObjectId()) {
String objectId = getIdFromParameters(client, rpcRequst); String objectId = getIdFromParameters(client, rpcRequst);
switch (operationType) { switch (operationType) {
case READ: case READ:
@ -131,16 +131,23 @@ public class DefaultLwM2MRpcRequestHandler implements LwM2MRpcRequestHandler {
throw new IllegalArgumentException("Unsupported operation: " + operationType.name()); throw new IllegalArgumentException("Unsupported operation: " + operationType.name());
} }
} else if (operationType.isComposite()) { } else if (operationType.isComposite()) {
switch (operationType) { if (client.isComposite(clientContext)) {
case READ_COMPOSITE: switch (operationType) {
sendReadCompositeRequest(client, rpcRequst); case READ_COMPOSITE:
break; sendReadCompositeRequest(client, rpcRequst);
case WRITE_COMPOSITE: break;
sendWriteCompositeRequest(client, rpcRequst); case WRITE_COMPOSITE:
break; sendWriteCompositeRequest(client, rpcRequst);
default: break;
throw new IllegalArgumentException("Unsupported operation: " + operationType.name()); default:
} throw new IllegalArgumentException("Unsupported operation: " + operationType.name());
}
}
else {
this.sendErrorRpcResponse(sessionInfo, rpcRequst.getRequestId(),
ResponseCode.INTERNAL_SERVER_ERROR.getName(), "This device does not support Composite Operation");
return;
}
} else { } else {
switch (operationType) { switch (operationType) {
case OBSERVE_CANCEL_ALL: case OBSERVE_CANCEL_ALL:
@ -239,6 +246,15 @@ public class DefaultLwM2MRpcRequestHandler implements LwM2MRpcRequestHandler {
downlinkHandler.sendWriteReplaceRequest(client, request, rpcCallback); downlinkHandler.sendWriteReplaceRequest(client, request, rpcCallback);
} }
/**
* Map<String, Object> nodes = new HashMap<>();
* nodes.put("/3/0/14", "+02");
* nodes.put("/1/0/2", 100);
* nodes.put("/5/0/1", "coap://localhost:5685");
* // defaultLwM2MDownlinkMsgHandler.sendWriteCompositeRequest(lwM2MClient, nodes, this);
* @param client
* @param requestMsg
*/
private void sendWriteCompositeRequest(LwM2mClient client, TransportProtos.ToDeviceRpcRequestMsg requestMsg) { private void sendWriteCompositeRequest(LwM2mClient client, TransportProtos.ToDeviceRpcRequestMsg requestMsg) {
RpcWriteCompositeRequest nodes = JacksonUtil.fromString(requestMsg.getParams(), RpcWriteCompositeRequest.class); RpcWriteCompositeRequest nodes = JacksonUtil.fromString(requestMsg.getParams(), RpcWriteCompositeRequest.class);
// TbLwM2MWriteReplaceRequest request = TbLwM2MWriteReplaceRequest.builder().versionedId(versionedId) // TbLwM2MWriteReplaceRequest request = TbLwM2MWriteReplaceRequest.builder().versionedId(versionedId)

13
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/rpc/RpcReadResponseCallback.java

@ -15,9 +15,6 @@
*/ */
package org.thingsboard.server.transport.lwm2m.server.rpc; package org.thingsboard.server.transport.lwm2m.server.rpc;
import org.eclipse.leshan.core.node.LwM2mObject;
import org.eclipse.leshan.core.node.LwM2mObjectInstance;
import org.eclipse.leshan.core.node.LwM2mResource;
import org.eclipse.leshan.core.request.LwM2mRequest; import org.eclipse.leshan.core.request.LwM2mRequest;
import org.eclipse.leshan.core.response.ReadResponse; import org.eclipse.leshan.core.response.ReadResponse;
import org.thingsboard.server.common.transport.TransportService; import org.thingsboard.server.common.transport.TransportService;
@ -35,14 +32,6 @@ public class RpcReadResponseCallback<R extends LwM2mRequest<T>, T extends ReadRe
@Override @Override
protected Optional<String> serializeSuccessfulResponse(T response) { protected Optional<String> serializeSuccessfulResponse(T response) {
Object value = null; return client.contentToString (response.getContent());
if (response.getContent() instanceof LwM2mObject) {
value = client.objectToString((LwM2mObject) response.getContent());
} else if (response.getContent() instanceof LwM2mObjectInstance) {
value = client.instanceToString((LwM2mObjectInstance) response.getContent());
} else if (response.getContent() instanceof LwM2mResource) {
value = client.resourceToString((LwM2mResource) response.getContent());
}
return Optional.of(String.format("%s", value));
} }
} }

3
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/rpc/composite/RpcReadResponseCompositeCallback.java

@ -16,7 +16,6 @@
package org.thingsboard.server.transport.lwm2m.server.rpc.composite; package org.thingsboard.server.transport.lwm2m.server.rpc.composite;
import org.eclipse.leshan.core.request.LwM2mRequest; import org.eclipse.leshan.core.request.LwM2mRequest;
import org.eclipse.leshan.core.request.ReadCompositeRequest;
import org.eclipse.leshan.core.response.ReadCompositeResponse; import org.eclipse.leshan.core.response.ReadCompositeResponse;
import org.thingsboard.server.common.transport.TransportService; import org.thingsboard.server.common.transport.TransportService;
import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.gen.transport.TransportProtos;
@ -34,6 +33,6 @@ public class RpcReadResponseCompositeCallback<R extends LwM2mRequest<T>, T exten
@Override @Override
protected Optional<String> serializeSuccessfulResponse(T response) { protected Optional<String> serializeSuccessfulResponse(T response) {
return Optional.of(String.format("%s", response.getContent().toString())); return client.contentToString (response.getContent());
} }
} }

12
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/uplink/DefaultLwM2MUplinkMsgHandler.java

@ -91,7 +91,6 @@ import javax.annotation.PreDestroy;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -427,17 +426,6 @@ public class DefaultLwM2MUplinkMsgHandler extends LwM2MExecutorAwareService impl
if (supportedObjects != null && supportedObjects.size() > 0) { if (supportedObjects != null && supportedObjects.size() > 0) {
// #1 // #1
this.sendReadRequests(lwM2MClient, profile, supportedObjects); this.sendReadRequests(lwM2MClient, profile, supportedObjects);
// test composite
String[] paths = new String[]{"/3/0", "/1/0", "/5/0"};
// String [] paths = new String[] {"/5"};
// String [] paths = new String[] {"/"};
// String [] paths = new String[] {"/9"};
// defaultLwM2MDownlinkMsgHandler.sendReadCompositeRequest(lwM2MClient, paths, this);
Map<String, Object> nodes = new HashMap<>();
nodes.put("/3/0/14", "+02");
nodes.put("/1/0/2", 100);
nodes.put("/5/0/1", "coap://localhost:5685");
// defaultLwM2MDownlinkMsgHandler.sendWriteCompositeRequest(lwM2MClient, nodes, this);
this.sendObserveRequests(lwM2MClient, profile, supportedObjects); this.sendObserveRequests(lwM2MClient, profile, supportedObjects);
this.sendWriteAttributeRequests(lwM2MClient, profile, supportedObjects); this.sendWriteAttributeRequests(lwM2MClient, profile, supportedObjects);
// Removed. Used only for debug. // Removed. Used only for debug.

Loading…
Cancel
Save