Browse Source

Refactoring of the Device profile update

pull/4718/head
Andrii Shvaika 5 years ago
parent
commit
3012e5e545
  1. 14
      common/data/src/main/java/org/thingsboard/server/common/data/device/data/lwm2m/ObjectAttributes.java
  2. 51
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/secure/LwM2MBootstrapSecurityStore.java
  3. 317
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2MUplinkMsgHandler.java
  4. 130
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportRequest.java
  5. 167
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportUtil.java
  6. 2
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mVersionedModelProvider.java
  7. 49
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClient.java
  8. 14
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientContext.java
  9. 40
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientContextImpl.java
  10. 113
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientProfile.java
  11. 10
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientRpcRequest.java
  12. 4
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/ParametersAnalyzeResult.java

14
common/data/src/main/java/org/thingsboard/server/common/data/device/data/lwm2m/ObjectAttributes.java

@ -15,17 +15,19 @@
*/
package org.thingsboard.server.common.data.device.data.lwm2m;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Data;
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ObjectAttributes {
private Integer dim;
private Long dim;
private String ver;
private Integer pmin;
private Integer pmax;
private Integer gt;
private Integer lt;
private Integer st;
private Long pmin;
private Long pmax;
private Double gt;
private Double lt;
private Double st;
}

51
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/secure/LwM2MBootstrapSecurityStore.java

@ -29,6 +29,8 @@ import org.eclipse.leshan.server.security.BootstrapSecurityStore;
import org.eclipse.leshan.server.security.SecurityInfo;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.stereotype.Service;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.common.data.device.data.lwm2m.BootstrapConfiguration;
import org.thingsboard.server.gen.transport.TransportProtos;
import org.thingsboard.server.transport.lwm2m.secure.TbLwM2MSecurityInfo;
import org.thingsboard.server.transport.lwm2m.secure.LwM2mCredentialsSecurityInfoValidator;
@ -151,35 +153,30 @@ public class LwM2MBootstrapSecurityStore implements BootstrapSecurityStore {
}
private LwM2MBootstrapConfig getParametersBootstrap(TbLwM2MSecurityInfo store) {
try {
LwM2MBootstrapConfig lwM2MBootstrapConfig = store.getBootstrapCredentialConfig();
if (lwM2MBootstrapConfig != null) {
ObjectMapper mapper = new ObjectMapper();
JsonObject bootstrapObject = getBootstrapParametersFromThingsboard(store.getDeviceProfile());
lwM2MBootstrapConfig.servers = mapper.readValue(bootstrapObject.get(SERVERS).toString(), LwM2MBootstrapServers.class);
LwM2MServerBootstrap profileServerBootstrap = mapper.readValue(bootstrapObject.get(BOOTSTRAP_SERVER).toString(), LwM2MServerBootstrap.class);
LwM2MServerBootstrap profileLwm2mServer = mapper.readValue(bootstrapObject.get(LWM2M_SERVER).toString(), LwM2MServerBootstrap.class);
UUID sessionUUiD = UUID.randomUUID();
TransportProtos.SessionInfoProto sessionInfo = helper.getValidateSessionInfo(store.getMsg(), sessionUUiD.getMostSignificantBits(), sessionUUiD.getLeastSignificantBits());
context.getTransportService().registerAsyncSession(sessionInfo, new LwM2mSessionMsgListener(null, sessionInfo));
if (this.getValidatedSecurityMode(lwM2MBootstrapConfig.bootstrapServer, profileServerBootstrap, lwM2MBootstrapConfig.lwm2mServer, profileLwm2mServer)) {
lwM2MBootstrapConfig.bootstrapServer = new LwM2MServerBootstrap(lwM2MBootstrapConfig.bootstrapServer, profileServerBootstrap);
lwM2MBootstrapConfig.lwm2mServer = new LwM2MServerBootstrap(lwM2MBootstrapConfig.lwm2mServer, profileLwm2mServer);
String logMsg = String.format("%s: getParametersBootstrap: %s Access connect client with bootstrap server.", LOG_LW2M_INFO, store.getEndpoint());
helper.sendParametersOnThingsboardTelemetry(helper.getKvStringtoThingsboard(LOG_LW2M_TELEMETRY, logMsg), sessionInfo);
return lwM2MBootstrapConfig;
} else {
log.error(" [{}] Different values SecurityMode between of client and profile.", store.getEndpoint());
log.error("{} getParametersBootstrap: [{}] Different values SecurityMode between of client and profile.", LOG_LW2M_ERROR, store.getEndpoint());
String logMsg = String.format("%s: getParametersBootstrap: %s Different values SecurityMode between of client and profile.", LOG_LW2M_ERROR, store.getEndpoint());
helper.sendParametersOnThingsboardTelemetry(helper.getKvStringtoThingsboard(LOG_LW2M_TELEMETRY, logMsg), sessionInfo);
return null;
}
LwM2MBootstrapConfig lwM2MBootstrapConfig = store.getBootstrapCredentialConfig();
if (lwM2MBootstrapConfig != null) {
BootstrapConfiguration bootstrapObject = getBootstrapParametersFromThingsboard(store.getDeviceProfile());
lwM2MBootstrapConfig.servers = JacksonUtil.fromString(JacksonUtil.toString(bootstrapObject.getServers()), LwM2MBootstrapServers.class);
LwM2MServerBootstrap profileServerBootstrap = JacksonUtil.fromString(JacksonUtil.toString(bootstrapObject.getBootstrapServer()), LwM2MServerBootstrap.class);
LwM2MServerBootstrap profileLwm2mServer = JacksonUtil.fromString(JacksonUtil.toString(bootstrapObject.getLwm2mServer()), LwM2MServerBootstrap.class);
UUID sessionUUiD = UUID.randomUUID();
TransportProtos.SessionInfoProto sessionInfo = helper.getValidateSessionInfo(store.getMsg(), sessionUUiD.getMostSignificantBits(), sessionUUiD.getLeastSignificantBits());
context.getTransportService().registerAsyncSession(sessionInfo, new LwM2mSessionMsgListener(null, sessionInfo));
if (this.getValidatedSecurityMode(lwM2MBootstrapConfig.bootstrapServer, profileServerBootstrap, lwM2MBootstrapConfig.lwm2mServer, profileLwm2mServer)) {
lwM2MBootstrapConfig.bootstrapServer = new LwM2MServerBootstrap(lwM2MBootstrapConfig.bootstrapServer, profileServerBootstrap);
lwM2MBootstrapConfig.lwm2mServer = new LwM2MServerBootstrap(lwM2MBootstrapConfig.lwm2mServer, profileLwm2mServer);
String logMsg = String.format("%s: getParametersBootstrap: %s Access connect client with bootstrap server.", LOG_LW2M_INFO, store.getEndpoint());
helper.sendParametersOnThingsboardTelemetry(helper.getKvStringtoThingsboard(LOG_LW2M_TELEMETRY, logMsg), sessionInfo);
return lwM2MBootstrapConfig;
} else {
log.error(" [{}] Different values SecurityMode between of client and profile.", store.getEndpoint());
log.error("{} getParametersBootstrap: [{}] Different values SecurityMode between of client and profile.", LOG_LW2M_ERROR, store.getEndpoint());
String logMsg = String.format("%s: getParametersBootstrap: %s Different values SecurityMode between of client and profile.", LOG_LW2M_ERROR, store.getEndpoint());
helper.sendParametersOnThingsboardTelemetry(helper.getKvStringtoThingsboard(LOG_LW2M_TELEMETRY, logMsg), sessionInfo);
return null;
}
} catch (JsonProcessingException e) {
log.error("Unable to decode Json or Certificate for [{}] [{}]", store.getEndpoint(), e.getMessage());
return null;
}
log.error("Unable to decode Json or Certificate for [{}]", store.getEndpoint());
return null;
}

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

@ -15,10 +15,8 @@
*/
package org.thingsboard.server.transport.lwm2m.server;
import com.fasterxml.jackson.core.type.TypeReference;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.reflect.TypeToken;
@ -36,15 +34,16 @@ import org.eclipse.leshan.core.response.ReadResponse;
import org.eclipse.leshan.server.registration.Registration;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.common.util.ThingsBoardExecutors;
import org.thingsboard.server.cache.ota.OtaPackageDataCache;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.data.device.data.lwm2m.ObjectAttributes;
import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTransportConfiguration;
import org.thingsboard.server.common.data.id.OtaPackageId;
import org.thingsboard.server.common.data.ota.OtaPackageKey;
import org.thingsboard.server.common.data.ota.OtaPackageType;
import org.thingsboard.server.common.data.ota.OtaPackageUtil;
import org.thingsboard.server.common.data.id.OtaPackageId;
import org.thingsboard.server.common.transport.TransportService;
import org.thingsboard.server.common.transport.TransportServiceCallback;
import org.thingsboard.server.common.transport.adaptor.AdaptorException;
@ -61,12 +60,11 @@ import org.thingsboard.server.transport.lwm2m.server.client.LwM2MClientState;
import org.thingsboard.server.transport.lwm2m.server.client.LwM2MClientStateException;
import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext;
import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientProfile;
import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientRpcRequest;
import org.thingsboard.server.transport.lwm2m.server.client.LwM2mFwSwUpdate;
import org.thingsboard.server.transport.lwm2m.server.client.ParametersAnalyzeResult;
import org.thingsboard.server.transport.lwm2m.server.client.ResourceValue;
import org.thingsboard.server.transport.lwm2m.server.client.ResultsAddKeyValueProto;
import org.thingsboard.server.transport.lwm2m.server.client.ResultsAnalyzerParameters;
import org.thingsboard.server.transport.lwm2m.server.store.TbLwM2MDtlsSessionStore;
import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl;
@ -82,16 +80,14 @@ import java.util.Random;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import static org.eclipse.californium.core.coap.CoAP.ResponseCode.BAD_REQUEST;
import static org.eclipse.leshan.core.attributes.Attribute.OBJECT_VERSION;
import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_PATH;
import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.FAILED;
import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.INITIATED;
import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_PATH;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportServerHelper.getValueFromKvProto;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.DEVICE_ATTRIBUTES_REQUEST;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_5_ID;
@ -102,18 +98,15 @@ import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.L
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_TELEMETRY;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_VALUE;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_WARN;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.DISCOVER;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.OBSERVE;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.OBSERVE_CANCEL;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.OBSERVE_CANCEL_ALL;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.READ;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.WRITE_ATTRIBUTES;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.WRITE_REPLACE;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SW_ID;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertJsonArrayToSet;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertOtaUpdateValueToString;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertPathFromIdVerToObjectId;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertPathFromObjectIdToIdVer;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.fromVersionedIdToObjectId;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.getAckCallback;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.isFwSwWords;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.setValidTypeOper;
@ -467,7 +460,7 @@ public class DefaultLwM2MUplinkMsgHandler implements LwM2mUplinkMsgHandler {
try {
LwM2mClient client = clientContext.getClientBySessionInfo(sessionInfo);
Registration registration = client.getRegistration();
if(registration != null) {
if (registration != null) {
lwm2mClientRpcRequest = new LwM2mClientRpcRequest(lwM2mTypeOper, bodyParams, toDeviceRpcRequestMsg.getRequestId(), sessionInfo, registration, this);
if (lwm2mClientRpcRequest.getErrorMsg() != null) {
lwm2mClientRpcRequest.setResponseCode(BAD_REQUEST.name());
@ -595,20 +588,72 @@ public class DefaultLwM2MUplinkMsgHandler implements LwM2mUplinkMsgHandler {
* @param lwM2MClient - object with All parameters off client
*/
private void initClientTelemetry(LwM2mClient lwM2MClient) {
LwM2mClientProfile profile = clientContext.getProfile(lwM2MClient.getProfileId());
Lwm2mDeviceProfileTransportConfiguration profile = clientContext.getProfile(lwM2MClient.getProfileId());
Set<String> supportedObjects = clientContext.getSupportedIdVerInClient(lwM2MClient);
if (supportedObjects != null && supportedObjects.size() > 0) {
if (LwM2mTransportUtil.LwM2MClientStrategy.CLIENT_STRATEGY_2.code == profile.getClientStrategy()) {
if (LwM2mTransportUtil.LwM2MClientStrategy.CLIENT_STRATEGY_2.code == profile.getClientLwM2mSettings().getClientOnlyObserveAfterConnect()) {
// #2
lwM2MClient.getPendingReadRequests().addAll(supportedObjects);
supportedObjects.forEach(path -> lwM2mTransportRequest.sendAllRequest(lwM2MClient, path, READ,
null, this.config.getTimeout(), null));
}
// #1
this.initReadAttrTelemetryObserveToClient(lwM2MClient, profile, READ, supportedObjects);
this.initReadAttrTelemetryObserveToClient(lwM2MClient, profile, OBSERVE, supportedObjects);
this.initReadAttrTelemetryObserveToClient(lwM2MClient, profile, WRITE_ATTRIBUTES, supportedObjects);
this.initReadAttrTelemetryObserveToClient(lwM2MClient, profile, DISCOVER, supportedObjects);
this.sendReadRequests(lwM2MClient, profile, supportedObjects);
this.sendObserveRequests(lwM2MClient, profile, supportedObjects);
this.sendWriteAttributeRequests(lwM2MClient, profile, supportedObjects);
// Removed. Used only for debug.
// this.sendDiscoverRequests(lwM2MClient, profile, supportedObjects);
}
}
private void sendReadRequests(LwM2mClient lwM2MClient, Lwm2mDeviceProfileTransportConfiguration profile, Set<String> supportedObjects) {
Set<String> targetIds = new HashSet<>(profile.getObserveAttr().getAttribute());
targetIds.addAll(profile.getObserveAttr().getTelemetry());
targetIds = targetIds.stream().filter(target -> isSupportedTargetId(supportedObjects, target)).collect(Collectors.toSet());
lwM2MClient.getPendingReadRequests().addAll(targetIds);
targetIds.forEach(targetId -> lwM2mTransportRequest.sendReadRequest(lwM2MClient, targetId, this.config.getTimeout()));
}
private void sendObserveRequests(LwM2mClient lwM2MClient, Lwm2mDeviceProfileTransportConfiguration profile, Set<String> supportedObjects) {
Set<String> targetIds = profile.getObserveAttr().getObserve();
targetIds = targetIds.stream().filter(target -> isSupportedTargetId(supportedObjects, target)).collect(Collectors.toSet());
// TODO: why do we need to put observe into pending read requests?
// lwM2MClient.getPendingReadRequests().addAll(targetIds);
targetIds.forEach(targetId -> lwM2mTransportRequest.sendObserveRequest(lwM2MClient, targetId, this.config.getTimeout()));
}
private void sendWriteAttributeRequests(LwM2mClient lwM2MClient, Lwm2mDeviceProfileTransportConfiguration profile, Set<String> supportedObjects) {
Map<String, ObjectAttributes> attributesMap = profile.getObserveAttr().getAttributeLwm2m();
attributesMap = attributesMap.entrySet().stream().filter(target -> isSupportedTargetId(supportedObjects, target.getKey())).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
// TODO: why do we need to put observe into pending read requests?
// lwM2MClient.getPendingReadRequests().addAll(targetIds);
attributesMap.forEach((targetId, params) -> lwM2mTransportRequest.sendWriteAttributesRequest(lwM2MClient, targetId, params, this.config.getTimeout()));
}
private void sendDiscoverRequests(LwM2mClient lwM2MClient, Lwm2mDeviceProfileTransportConfiguration profile, Set<String> supportedObjects) {
Set<String> targetIds = profile.getObserveAttr().getAttributeLwm2m().keySet();
targetIds = targetIds.stream().filter(target -> isSupportedTargetId(supportedObjects, target)).collect(Collectors.toSet());
// TODO: why do we need to put observe into pending read requests?
// lwM2MClient.getPendingReadRequests().addAll(targetIds);
targetIds.forEach(targetId -> lwM2mTransportRequest.sendDiscoverRequest(lwM2MClient, targetId, this.config.getTimeout()));
}
private void sendRequestsToClient(LwM2mClient lwM2MClient, LwM2mTypeOper operationType, Set<String> supportedObjectIds, Set<String> desiredObjectIds, ConcurrentHashMap<String, ObjectAttributes> params) {
if (desiredObjectIds != null && !desiredObjectIds.isEmpty()) {
Set<String> targetObjectIds = desiredObjectIds.stream().filter(target -> isSupportedTargetId(supportedObjectIds, target)
).collect(Collectors.toUnmodifiableSet());
if (!targetObjectIds.isEmpty()) {
//TODO: remove this side effect?
lwM2MClient.getPendingReadRequests().addAll(targetObjectIds);
targetObjectIds.forEach(target -> {
Object additionalParams = params != null ? params.get(target) : null;
lwM2mTransportRequest.sendAllRequest(lwM2MClient, target, operationType, additionalParams, this.config.getTimeout(), null);
});
if (OBSERVE.equals(operationType)) {
lwM2MClient.initReadValue(this, null);
}
}
}
}
@ -618,7 +663,7 @@ public class DefaultLwM2MUplinkMsgHandler implements LwM2mUplinkMsgHandler {
* @param pathIdVer -
*/
private void updateObjectResourceValue(Registration registration, LwM2mObject lwM2mObject, String pathIdVer) {
LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(pathIdVer));
LwM2mPath pathIds = new LwM2mPath(fromVersionedIdToObjectId(pathIdVer));
lwM2mObject.getInstances().forEach((instanceId, instance) -> {
String pathInstance = pathIds.toString() + "/" + instanceId;
this.updateObjectInstanceResourceValue(registration, instance, pathInstance);
@ -631,7 +676,7 @@ public class DefaultLwM2MUplinkMsgHandler implements LwM2mUplinkMsgHandler {
* @param pathIdVer -
*/
private void updateObjectInstanceResourceValue(Registration registration, LwM2mObjectInstance lwM2mObjectInstance, String pathIdVer) {
LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(pathIdVer));
LwM2mPath pathIds = new LwM2mPath(fromVersionedIdToObjectId(pathIdVer));
lwM2mObjectInstance.getResources().forEach((resourceId, resource) -> {
String pathRez = pathIds.toString() + "/" + resourceId;
this.updateResourcesValue(registration, resource, pathRez);
@ -668,9 +713,7 @@ public class DefaultLwM2MUplinkMsgHandler implements LwM2mUplinkMsgHandler {
log.warn("93) path: [{}] value: [{}]", path, lwM2mResource.getValue());
fwUpdate.updateStateOta(this, lwM2mTransportRequest, registration, path, ((Long) lwM2mResource.getValue()).intValue());
}
Set<String> paths = new HashSet<>();
paths.add(path);
this.updateAttrTelemetry(registration, paths);
this.updateAttrTelemetry(registration, Collections.singleton(path));
} else {
log.error("Fail update Resource [{}]", lwM2mResource);
}
@ -703,47 +746,6 @@ public class DefaultLwM2MUplinkMsgHandler implements LwM2mUplinkMsgHandler {
}
}
private void initReadAttrTelemetryObserveToClient(LwM2mClient lwM2MClient, LwM2mClientProfile lwM2MClientProfile, LwM2mTypeOper typeOper, Set<String> supportedObjects) {
Set<String> result = null;
ConcurrentHashMap<String, Object> params = null;
if (READ.equals(typeOper)) {
result = JacksonUtil.fromString(lwM2MClientProfile.getPostAttributeProfile().toString(),
new TypeReference<>() {
});
result.addAll(JacksonUtil.fromString(lwM2MClientProfile.getPostTelemetryProfile().toString(),
new TypeReference<>() {
}));
} else if (OBSERVE.equals(typeOper)) {
result = JacksonUtil.fromString(lwM2MClientProfile.getPostObserveProfile().toString(),
new TypeReference<>() {
});
} else if (DISCOVER.equals(typeOper)) {
result = this.getPathForWriteAttributes(lwM2MClientProfile.getPostAttributeLwm2mProfile()).keySet();
} else if (WRITE_ATTRIBUTES.equals(typeOper)) {
params = this.getPathForWriteAttributes(lwM2MClientProfile.getPostAttributeLwm2mProfile());
result = params.keySet();
}
sendRequestsToClient(lwM2MClient, typeOper, supportedObjects, result, params);
}
private void sendRequestsToClient(LwM2mClient lwM2MClient, LwM2mTypeOper operationType, Set<String> supportedObjectIds, Set<String> desiredObjectIds, ConcurrentHashMap<String, Object> params) {
if (desiredObjectIds != null && !desiredObjectIds.isEmpty()) {
Set<String> targetObjectIds = desiredObjectIds.stream().filter(target -> isSupportedTargetId(supportedObjectIds, target)
).collect(Collectors.toUnmodifiableSet());
if (!targetObjectIds.isEmpty()) {
//TODO: remove this side effect?
lwM2MClient.getPendingReadRequests().addAll(targetObjectIds);
targetObjectIds.forEach(target -> {
Object additionalParams = params != null ? params.get(target) : null;
lwM2mTransportRequest.sendAllRequest(lwM2MClient, target, operationType, additionalParams, this.config.getTimeout(), null);
});
if (OBSERVE.equals(operationType)) {
lwM2MClient.initReadValue(this, null);
}
}
}
}
private boolean isSupportedTargetId(Set<String> supportedIds, String targetId) {
String[] targetIdParts = targetId.split(LWM2M_SEPARATOR_PATH);
if (targetIdParts.length <= 1) {
@ -781,20 +783,20 @@ public class DefaultLwM2MUplinkMsgHandler implements LwM2mUplinkMsgHandler {
private ResultsAddKeyValueProto getParametersFromProfile(Registration registration, Set<String> path) {
if (path != null && path.size() > 0) {
ResultsAddKeyValueProto results = new ResultsAddKeyValueProto();
LwM2mClientProfile lwM2MClientProfile = clientContext.getProfile(registration);
var profile = clientContext.getProfile(registration);
List<TransportProtos.KeyValueProto> resultAttributes = new ArrayList<>();
lwM2MClientProfile.getPostAttributeProfile().forEach(pathIdVer -> {
if (path.contains(pathIdVer.getAsString())) {
TransportProtos.KeyValueProto kvAttr = this.getKvToThingsboard(pathIdVer.getAsString(), registration);
profile.getObserveAttr().getAttribute().forEach(pathIdVer -> {
if (path.contains(pathIdVer)) {
TransportProtos.KeyValueProto kvAttr = this.getKvToThingsboard(pathIdVer, registration);
if (kvAttr != null) {
resultAttributes.add(kvAttr);
}
}
});
List<TransportProtos.KeyValueProto> resultTelemetries = new ArrayList<>();
lwM2MClientProfile.getPostTelemetryProfile().forEach(pathIdVer -> {
if (path.contains(pathIdVer.getAsString())) {
TransportProtos.KeyValueProto kvAttr = this.getKvToThingsboard(pathIdVer.getAsString(), registration);
profile.getObserveAttr().getTelemetry().forEach(pathIdVer -> {
if (path.contains(pathIdVer)) {
TransportProtos.KeyValueProto kvAttr = this.getKvToThingsboard(pathIdVer, registration);
if (kvAttr != null) {
resultTelemetries.add(kvAttr);
}
@ -813,12 +815,12 @@ public class DefaultLwM2MUplinkMsgHandler implements LwM2mUplinkMsgHandler {
private TransportProtos.KeyValueProto getKvToThingsboard(String pathIdVer, Registration registration) {
LwM2mClient lwM2MClient = this.clientContext.getClientByEndpoint(registration.getEndpoint());
JsonObject names = clientContext.getProfiles().get(lwM2MClient.getProfileId()).getPostKeyNameProfile();
if (names != null && names.has(pathIdVer)) {
String resourceName = names.get(pathIdVer).getAsString();
Map<String, String> names = clientContext.getProfile(lwM2MClient.getProfileId()).getObserveAttr().getKeyName();
if (names != null && names.containsKey(pathIdVer)) {
String resourceName = names.get(pathIdVer);
if (resourceName != null && !resourceName.isEmpty()) {
try {
LwM2mResource resourceValue = lwM2MClient != null ? getResourceValueFromLwM2MClient(lwM2MClient, pathIdVer) : null;
LwM2mResource resourceValue = getResourceValueFromLwM2MClient(lwM2MClient, pathIdVer);
if (resourceValue != null) {
ResourceModel.Type currentType = resourceValue.getType();
ResourceModel.Type expectedType = this.helper.getResourceModelTypeEqualsKvProtoValueType(currentType, pathIdVer);
@ -830,14 +832,14 @@ public class DefaultLwM2MUplinkMsgHandler implements LwM2mUplinkMsgHandler {
ResourceModel.Type finalCurrentType = currentType;
resourceValue.getInstances().forEach((k, v) -> {
Object val = this.converter.convertValue(v, finalCurrentType, expectedType,
new LwM2mPath(convertPathFromIdVerToObjectId(pathIdVer)));
new LwM2mPath(fromVersionedIdToObjectId(pathIdVer)));
JsonElement element = gson.toJsonTree(val, val.getClass());
((JsonObject) finalvalueKvProto).add(String.valueOf(k), element);
});
valueKvProto = gson.toJson(valueKvProto);
} else {
valueKvProto = this.converter.convertValue(resourceValue.getValue(), currentType, expectedType,
new LwM2mPath(convertPathFromIdVerToObjectId(pathIdVer)));
new LwM2mPath(fromVersionedIdToObjectId(pathIdVer)));
}
LwM2mOtaConvert lwM2mOtaConvert = convertOtaUpdateValueToString(pathIdVer, valueKvProto, currentType);
valueKvProto = lwM2mOtaConvert.getValue();
@ -864,7 +866,7 @@ public class DefaultLwM2MUplinkMsgHandler implements LwM2mUplinkMsgHandler {
ResourceModel.Type currentType = resourceValue.getType();
ResourceModel.Type expectedType = this.helper.getResourceModelTypeEqualsKvProtoValueType(currentType, pathIdVer);
return this.converter.convertValue(resourceValue.getValue(), currentType, expectedType,
new LwM2mPath(convertPathFromIdVerToObjectId(pathIdVer)));
new LwM2mPath(fromVersionedIdToObjectId(pathIdVer)));
} else {
return null;
}
@ -879,7 +881,7 @@ public class DefaultLwM2MUplinkMsgHandler implements LwM2mUplinkMsgHandler {
LwM2mResource lwm2mResourceValue = null;
ResourceValue resourceValue = lwM2MClient.getResources().get(path);
if (resourceValue != null) {
if (new LwM2mPath(convertPathFromIdVerToObjectId(path)).isResource()) {
if (new LwM2mPath(fromVersionedIdToObjectId(path)).isResource()) {
lwm2mResourceValue = lwM2MClient.getResources().get(path).getLwM2mResource();
}
}
@ -929,53 +931,42 @@ public class DefaultLwM2MUplinkMsgHandler implements LwM2mUplinkMsgHandler {
* @param clients -
* @param deviceProfile -
*/
//TODO: review and optimize the logic to minimize number of the requests to device.
private void onDeviceProfileUpdate(List<LwM2mClient> clients, DeviceProfile deviceProfile) {
LwM2mClientProfile lwM2MClientProfileOld = clientContext.getProfiles().get(deviceProfile.getUuidId()).clone();
var oldProfile = clientContext.getProfile(deviceProfile.getUuidId());
if (clientContext.profileUpdate(deviceProfile) != null) {
// #1
JsonArray attributeOld = lwM2MClientProfileOld.getPostAttributeProfile();
Set<String> attributeSetOld = convertJsonArrayToSet(attributeOld);
JsonArray telemetryOld = lwM2MClientProfileOld.getPostTelemetryProfile();
Set<String> telemetrySetOld = convertJsonArrayToSet(telemetryOld);
JsonArray observeOld = lwM2MClientProfileOld.getPostObserveProfile();
JsonObject keyNameOld = lwM2MClientProfileOld.getPostKeyNameProfile();
JsonObject attributeLwm2mOld = lwM2MClientProfileOld.getPostAttributeLwm2mProfile();
LwM2mClientProfile lwM2MClientProfileNew = clientContext.getProfiles().get(deviceProfile.getUuidId()).clone();
JsonArray attributeNew = lwM2MClientProfileNew.getPostAttributeProfile();
Set<String> attributeSetNew = convertJsonArrayToSet(attributeNew);
JsonArray telemetryNew = lwM2MClientProfileNew.getPostTelemetryProfile();
Set<String> telemetrySetNew = convertJsonArrayToSet(telemetryNew);
JsonArray observeNew = lwM2MClientProfileNew.getPostObserveProfile();
JsonObject keyNameNew = lwM2MClientProfileNew.getPostKeyNameProfile();
JsonObject attributeLwm2mNew = lwM2MClientProfileNew.getPostAttributeLwm2mProfile();
Set<String> attributeSetOld = oldProfile.getObserveAttr().getAttribute();
Set<String> telemetrySetOld = oldProfile.getObserveAttr().getTelemetry();
Set<String> observeOld = oldProfile.getObserveAttr().getObserve();
Map<String, String> keyNameOld = oldProfile.getObserveAttr().getKeyName();
Map<String, ObjectAttributes> attributeLwm2mOld = oldProfile.getObserveAttr().getAttributeLwm2m();
var newProfile = clientContext.getProfile(deviceProfile.getUuidId());
Set<String> attributeSetNew = newProfile.getObserveAttr().getAttribute();
Set<String> telemetrySetNew = newProfile.getObserveAttr().getTelemetry();
Set<String> observeNew = newProfile.getObserveAttr().getObserve();
Map<String, String> keyNameNew = newProfile.getObserveAttr().getKeyName();
Map<String, ObjectAttributes> attributeLwm2mNew = newProfile.getObserveAttr().getAttributeLwm2m();
// #3
ResultsAnalyzerParameters sendAttrToThingsboard = new ResultsAnalyzerParameters();
ParametersAnalyzeResult diff = new ParametersAnalyzeResult();
// #3.1
if (!attributeOld.equals(attributeNew)) {
ResultsAnalyzerParameters postAttributeAnalyzer = this.getAnalyzerParameters(new Gson().fromJson(attributeOld,
new TypeToken<Set<String>>() {
}.getType()), attributeSetNew);
sendAttrToThingsboard.getPathPostParametersAdd().addAll(postAttributeAnalyzer.getPathPostParametersAdd());
sendAttrToThingsboard.getPathPostParametersDel().addAll(postAttributeAnalyzer.getPathPostParametersDel());
if (!attributeSetOld.equals(attributeSetNew)) {
ParametersAnalyzeResult postAttributeAnalyzer = this.getAnalyzerParameters(attributeSetOld, attributeSetNew);
diff.getPathPostParametersAdd().addAll(postAttributeAnalyzer.getPathPostParametersAdd());
diff.getPathPostParametersDel().addAll(postAttributeAnalyzer.getPathPostParametersDel());
}
// #3.2
if (!telemetryOld.equals(telemetryNew)) {
ResultsAnalyzerParameters postTelemetryAnalyzer = this.getAnalyzerParameters(new Gson().fromJson(telemetryOld,
new TypeToken<Set<String>>() {
}.getType()), telemetrySetNew);
sendAttrToThingsboard.getPathPostParametersAdd().addAll(postTelemetryAnalyzer.getPathPostParametersAdd());
sendAttrToThingsboard.getPathPostParametersDel().addAll(postTelemetryAnalyzer.getPathPostParametersDel());
if (!telemetrySetOld.equals(telemetrySetNew)) {
ParametersAnalyzeResult postTelemetryAnalyzer = this.getAnalyzerParameters(telemetrySetOld, telemetrySetNew);
diff.getPathPostParametersAdd().addAll(postTelemetryAnalyzer.getPathPostParametersAdd());
diff.getPathPostParametersDel().addAll(postTelemetryAnalyzer.getPathPostParametersDel());
}
// #3.3
if (!keyNameOld.equals(keyNameNew)) {
ResultsAnalyzerParameters keyNameChange = this.getAnalyzerKeyName(new Gson().fromJson(keyNameOld.toString(),
new TypeToken<ConcurrentHashMap<String, String>>() {
}.getType()),
new Gson().fromJson(keyNameNew.toString(), new TypeToken<ConcurrentHashMap<String, String>>() {
}.getType()));
sendAttrToThingsboard.getPathPostParametersAdd().addAll(keyNameChange.getPathPostParametersAdd());
ParametersAnalyzeResult keyNameChange = this.getAnalyzerKeyName(keyNameOld, keyNameNew);
diff.getPathPostParametersAdd().addAll(keyNameChange.getPathPostParametersAdd());
}
// #3.4, #6
@ -984,32 +975,28 @@ public class DefaultLwM2MUplinkMsgHandler implements LwM2mUplinkMsgHandler {
}
// #4.1 add
if (sendAttrToThingsboard.getPathPostParametersAdd().size() > 0) {
if (diff.getPathPostParametersAdd().size() > 0) {
// update value in Resources
clients.forEach(client -> {
this.readObserveFromProfile(client, sendAttrToThingsboard.getPathPostParametersAdd(), READ);
this.readObserveFromProfile(client, diff.getPathPostParametersAdd(), READ);
});
}
// #4.2 del
if (sendAttrToThingsboard.getPathPostParametersDel().size() > 0) {
ResultsAnalyzerParameters sendAttrToThingsboardDel = this.getAnalyzerParameters(sendAttrToThingsboard.getPathPostParametersAdd(), sendAttrToThingsboard.getPathPostParametersDel());
sendAttrToThingsboard.setPathPostParametersDel(sendAttrToThingsboardDel.getPathPostParametersDel());
if (diff.getPathPostParametersDel().size() > 0) {
ParametersAnalyzeResult sendAttrToThingsboardDel = this.getAnalyzerParameters(diff.getPathPostParametersAdd(), diff.getPathPostParametersDel());
diff.setPathPostParametersDel(sendAttrToThingsboardDel.getPathPostParametersDel());
}
// #5.1
if (!observeOld.equals(observeNew)) {
Set<String> observeSetOld = new Gson().fromJson(observeOld, new TypeToken<Set<String>>() {
}.getType());
Set<String> observeSetNew = new Gson().fromJson(observeNew, new TypeToken<Set<String>>() {
}.getType());
//#5.2 add
// path Attr/Telemetry includes newObserve
attributeSetOld.addAll(telemetrySetOld);
ResultsAnalyzerParameters sendObserveToClientOld = this.getAnalyzerParametersIn(attributeSetOld, observeSetOld); // add observe
ParametersAnalyzeResult sendObserveToClientOld = this.getAnalyzerParametersIn(attributeSetOld, observeOld); // add observe
attributeSetNew.addAll(telemetrySetNew);
ResultsAnalyzerParameters sendObserveToClientNew = this.getAnalyzerParametersIn(attributeSetNew, observeSetNew); // add observe
ParametersAnalyzeResult sendObserveToClientNew = this.getAnalyzerParametersIn(attributeSetNew, observeNew); // add observe
// does not include oldObserve
ResultsAnalyzerParameters postObserveAnalyzer = this.getAnalyzerParameters(sendObserveToClientOld.getPathPostParametersAdd(), sendObserveToClientNew.getPathPostParametersAdd());
ParametersAnalyzeResult postObserveAnalyzer = this.getAnalyzerParameters(sendObserveToClientOld.getPathPostParametersAdd(), sendObserveToClientNew.getPathPostParametersAdd());
// send Request observe to Client
clients.forEach(client -> {
Registration registration = client.getRegistration();
@ -1033,10 +1020,10 @@ public class DefaultLwM2MUplinkMsgHandler implements LwM2mUplinkMsgHandler {
* @param parametersNew -
* @return ResultsAnalyzerParameters: add && new
*/
private ResultsAnalyzerParameters getAnalyzerParameters(Set<String> parametersOld, Set<String> parametersNew) {
ResultsAnalyzerParameters analyzerParameters = null;
private ParametersAnalyzeResult getAnalyzerParameters(Set<String> parametersOld, Set<String> parametersNew) {
ParametersAnalyzeResult analyzerParameters = null;
if (!parametersOld.equals(parametersNew)) {
analyzerParameters = new ResultsAnalyzerParameters();
analyzerParameters = new ParametersAnalyzeResult();
analyzerParameters.setPathPostParametersAdd(parametersNew
.stream().filter(p -> !parametersOld.contains(p)).collect(Collectors.toSet()));
analyzerParameters.setPathPostParametersDel(parametersOld
@ -1045,8 +1032,8 @@ public class DefaultLwM2MUplinkMsgHandler implements LwM2mUplinkMsgHandler {
return analyzerParameters;
}
private ResultsAnalyzerParameters getAnalyzerParametersIn(Set<String> parametersObserve, Set<String> parameters) {
ResultsAnalyzerParameters analyzerParameters = new ResultsAnalyzerParameters();
private ParametersAnalyzeResult getAnalyzerParametersIn(Set<String> parametersObserve, Set<String> parameters) {
ParametersAnalyzeResult analyzerParameters = new ParametersAnalyzeResult();
analyzerParameters.setPathPostParametersAdd(parametersObserve
.stream().filter(parameters::contains).collect(Collectors.toSet()));
return analyzerParameters;
@ -1060,7 +1047,7 @@ public class DefaultLwM2MUplinkMsgHandler implements LwM2mUplinkMsgHandler {
*/
private void readObserveFromProfile(LwM2mClient client, Set<String> targets, LwM2mTypeOper typeOper) {
targets.forEach(target -> {
LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(target));
LwM2mPath pathIds = new LwM2mPath(fromVersionedIdToObjectId(target));
if (pathIds.isResource()) {
if (READ.equals(typeOper)) {
lwM2mTransportRequest.sendAllRequest(client, target, typeOper,
@ -1073,8 +1060,8 @@ public class DefaultLwM2MUplinkMsgHandler implements LwM2mUplinkMsgHandler {
});
}
private ResultsAnalyzerParameters getAnalyzerKeyName(ConcurrentHashMap<String, String> keyNameOld, ConcurrentHashMap<String, String> keyNameNew) {
ResultsAnalyzerParameters analyzerParameters = new ResultsAnalyzerParameters();
private ParametersAnalyzeResult getAnalyzerKeyName(Map<String, String> keyNameOld, Map<String, String> keyNameNew) {
ParametersAnalyzeResult analyzerParameters = new ParametersAnalyzeResult();
Set<String> paths = keyNameNew.entrySet()
.stream()
.filter(e -> !e.getValue().equals(keyNameOld.get(e.getKey())))
@ -1084,23 +1071,12 @@ public class DefaultLwM2MUplinkMsgHandler implements LwM2mUplinkMsgHandler {
}
/**
* #3.4, #6
* #6
* #6.1 - send update WriteAttribute
* #6.2 - send empty WriteAttribute
*
* @param attributeLwm2mOld -
* @param attributeLwm2mNew -
* @return
*/
private void getAnalyzerAttributeLwm2m(List<LwM2mClient> clients, JsonObject attributeLwm2mOld, JsonObject attributeLwm2mNew) {
ResultsAnalyzerParameters analyzerParameters = new ResultsAnalyzerParameters();
ConcurrentHashMap<String, Object> lwm2mAttributesOld = new Gson().fromJson(attributeLwm2mOld.toString(),
new TypeToken<ConcurrentHashMap<String, Object>>() {
}.getType());
ConcurrentHashMap<String, Object> lwm2mAttributesNew = new Gson().fromJson(attributeLwm2mNew.toString(),
new TypeToken<ConcurrentHashMap<String, Object>>() {
}.getType());
private void getAnalyzerAttributeLwm2m(List<LwM2mClient> clients, Map<String, ObjectAttributes> lwm2mAttributesOld, Map<String, ObjectAttributes> lwm2mAttributesNew) {
ParametersAnalyzeResult analyzerParameters = new ParametersAnalyzeResult();
Set<String> pathOld = lwm2mAttributesOld.keySet();
Set<String> pathNew = lwm2mAttributesNew.keySet();
analyzerParameters.setPathPostParametersAdd(pathNew
@ -1108,7 +1084,7 @@ public class DefaultLwM2MUplinkMsgHandler implements LwM2mUplinkMsgHandler {
analyzerParameters.setPathPostParametersDel(pathOld
.stream().filter(p -> !pathNew.contains(p)).collect(Collectors.toSet()));
Set<String> pathCommon = pathNew
.stream().filter(p -> pathOld.contains(p)).collect(Collectors.toSet());
.stream().filter(pathOld::contains).collect(Collectors.toSet());
Set<String> pathCommonChange = pathCommon
.stream().filter(p -> !lwm2mAttributesOld.get(p).equals(lwm2mAttributesNew.get(p))).collect(Collectors.toSet());
analyzerParameters.getPathPostParametersAdd().addAll(pathCommonChange);
@ -1120,30 +1096,21 @@ public class DefaultLwM2MUplinkMsgHandler implements LwM2mUplinkMsgHandler {
Set<String> pathSend = analyzerParameters.getPathPostParametersAdd().stream().filter(target -> clientObjects.contains("/" + target.split(LWM2M_SEPARATOR_PATH)[1]))
.collect(Collectors.toUnmodifiableSet());
if (!pathSend.isEmpty()) {
ConcurrentHashMap<String, Object> finalParams = lwm2mAttributesNew;
pathSend.forEach(target -> lwM2mTransportRequest.sendAllRequest(client, target, WRITE_ATTRIBUTES,
finalParams.get(target), this.config.getTimeout(), null));
pathSend.forEach(target -> lwM2mTransportRequest.sendWriteAttributesRequest(client, target, lwm2mAttributesNew.get(target), this.config.getTimeout()));
}
});
}
// #6.2
if (analyzerParameters.getPathPostParametersDel().size() > 0) {
clients.forEach(client -> {
Registration registration = client.getRegistration();
Set<String> clientObjects = clientContext.getSupportedIdVerInClient(client);
Set<String> pathSend = analyzerParameters.getPathPostParametersDel().stream().filter(target -> clientObjects.contains("/" + target.split(LWM2M_SEPARATOR_PATH)[1]))
.collect(Collectors.toUnmodifiableSet());
if (!pathSend.isEmpty()) {
pathSend.forEach(target -> {
Map<String, Object> params = (Map<String, Object>) lwm2mAttributesOld.get(target);
params.clear();
params.put(OBJECT_VERSION, "");
lwM2mTransportRequest.sendAllRequest(client, target, WRITE_ATTRIBUTES, params, this.config.getTimeout(), null);
});
pathSend.forEach(target -> lwM2mTransportRequest.sendWriteAttributesRequest(client, target, new ObjectAttributes(), this.config.getTimeout()));
}
});
}
}
private void cancelObserveFromProfile(LwM2mClient lwM2mClient, Set<String> paramAnallyzer) {
@ -1183,10 +1150,10 @@ public class DefaultLwM2MUplinkMsgHandler implements LwM2mUplinkMsgHandler {
* @return -
*/
public String getPresentPathIntoProfile(TransportProtos.SessionInfoProto sessionInfo, String name) {
LwM2mClientProfile profile = clientContext.getProfile(new UUID(sessionInfo.getDeviceProfileIdMSB(), sessionInfo.getDeviceProfileIdLSB()));
var profile = clientContext.getProfile(new UUID(sessionInfo.getDeviceProfileIdMSB(), sessionInfo.getDeviceProfileIdLSB()));
LwM2mClient lwM2mClient = clientContext.getClientBySessionInfo(sessionInfo);
return profile.getPostKeyNameProfile().getAsJsonObject().entrySet().stream()
.filter(e -> e.getValue().getAsString().equals(name) && validateResourceInModel(lwM2mClient, e.getKey(), false)).findFirst().map(Map.Entry::getKey)
return profile.getObserveAttr().getKeyName().entrySet().stream()
.filter(e -> e.getValue().equals(name) && validateResourceInModel(lwM2mClient, e.getKey(), false)).findFirst().map(Map.Entry::getKey)
.orElse(null);
}
@ -1292,7 +1259,7 @@ public class DefaultLwM2MUplinkMsgHandler implements LwM2mUplinkMsgHandler {
SessionInfoProto sessionInfo = this.getSessionInfo(lwM2MClient);
if (sessionInfo != null) {
//#1.1
ConcurrentMap<String, String> keyNamesMap = this.getNamesFromProfileForSharedAttributes(lwM2MClient);
Map<String, String> keyNamesMap = this.getNamesFromProfileForSharedAttributes(lwM2MClient);
if (keyNamesMap.values().size() > 0) {
try {
//#1.2
@ -1401,25 +1368,15 @@ public class DefaultLwM2MUplinkMsgHandler implements LwM2mUplinkMsgHandler {
.build();
}
/**
* !!! sharedAttr === profileAttr !!!
* Get names or keyNames from profile: resources IsWritable
*
* @param lwM2MClient -
* @return ArrayList keyNames from profile profileAttr && IsWritable
*/
private ConcurrentMap<String, String> getNamesFromProfileForSharedAttributes(LwM2mClient lwM2MClient) {
LwM2mClientProfile profile = clientContext.getProfile(lwM2MClient.getProfileId());
return new Gson().fromJson(profile.getPostKeyNameProfile().toString(),
new TypeToken<ConcurrentHashMap<String, String>>() {
}.getType());
private Map<String, String> getNamesFromProfileForSharedAttributes(LwM2mClient lwM2MClient) {
Lwm2mDeviceProfileTransportConfiguration profile = clientContext.getProfile(lwM2MClient.getProfileId());
return profile.getObserveAttr().getKeyName();
}
private boolean validateResourceInModel(LwM2mClient lwM2mClient, String pathIdVer, boolean isWritableNotOptional) {
ResourceModel resourceModel = lwM2mClient.getResourceModel(pathIdVer, this.config
.getModelProvider());
Integer objectId = new LwM2mPath(convertPathFromIdVerToObjectId(pathIdVer)).getObjectId();
Integer objectId = new LwM2mPath(fromVersionedIdToObjectId(pathIdVer)).getObjectId();
String objectVer = validateObjectVerFromKey(pathIdVer);
return resourceModel != null && (isWritableNotOptional ?
objectId != null && objectVer != null && objectVer.equals(lwM2mClient.getRegistration().getSupportedVersion(objectId)) && resourceModel.operations.isWritable() :

130
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportRequest.java

@ -20,6 +20,8 @@ import lombok.extern.slf4j.Slf4j;
import org.eclipse.californium.core.coap.CoAP;
import org.eclipse.californium.core.coap.Response;
import org.eclipse.leshan.core.Link;
import org.eclipse.leshan.core.attributes.Attribute;
import org.eclipse.leshan.core.attributes.AttributeSet;
import org.eclipse.leshan.core.model.ResourceModel;
import org.eclipse.leshan.core.node.LwM2mNode;
import org.eclipse.leshan.core.node.LwM2mObject;
@ -51,6 +53,8 @@ import org.eclipse.leshan.core.util.Hex;
import org.eclipse.leshan.core.util.NamedThreadFactory;
import org.eclipse.leshan.server.registration.Registration;
import org.springframework.stereotype.Service;
import org.thingsboard.server.common.data.StringUtils;
import org.thingsboard.server.common.data.device.data.lwm2m.ObjectAttributes;
import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;
import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig;
import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
@ -62,15 +66,26 @@ import javax.annotation.PostConstruct;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import static org.eclipse.californium.core.coap.CoAP.ResponseCode.CONTENT;
import static org.eclipse.leshan.core.ResponseCode.BAD_REQUEST;
import static org.eclipse.leshan.core.ResponseCode.NOT_FOUND;
import static org.eclipse.leshan.core.attributes.Attribute.DIMENSION;
import static org.eclipse.leshan.core.attributes.Attribute.GREATER_THAN;
import static org.eclipse.leshan.core.attributes.Attribute.LESSER_THAN;
import static org.eclipse.leshan.core.attributes.Attribute.MAXIMUM_PERIOD;
import static org.eclipse.leshan.core.attributes.Attribute.MINIMUM_PERIOD;
import static org.eclipse.leshan.core.attributes.Attribute.OBJECT_VERSION;
import static org.eclipse.leshan.core.attributes.Attribute.STEP;
import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.DOWNLOADED;
import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.FAILED;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportServerHelper.getContentFormatByResourceModelType;
@ -91,7 +106,7 @@ import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.L
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.RESPONSE_REQUEST_CHANNEL;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SW_INSTALL_ID;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SW_PACKAGE_ID;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertPathFromIdVerToObjectId;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.fromVersionedIdToObjectId;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertPathFromObjectIdToIdVer;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.createWriteAttributeRequest;
@ -116,33 +131,105 @@ public class LwM2mTransportRequest {
new NamedThreadFactory(String.format("LwM2M %s channel response after request", RESPONSE_REQUEST_CHANNEL)));
}
public void sendReadRequest(LwM2mClient lwM2MClient, String targetId, Long timeout) {
sendReadRequest(lwM2MClient, targetId, lwM2MClient.getDefaultContentFormat(), timeout);
}
public void sendReadRequest(LwM2mClient lwM2MClient, String targetId, ContentFormat contentFormat, Long timeout) {
String objectId = fromVersionedIdToObjectId(targetId);
if (objectId != null && lwM2MClient.isValidObjectVersion(targetId)) {
sendRequest(lwM2MClient, new ReadRequest(contentFormat, objectId), timeout);
}
}
public void sendObserveRequest(LwM2mClient lwM2MClient, String targetId, Long timeout) {
sendObserveRequest(lwM2MClient, targetId, lwM2MClient.getDefaultContentFormat(), timeout);
}
public void sendObserveRequest(LwM2mClient lwM2MClient, String targetId, ContentFormat contentFormat, Long timeout) {
String objectId = fromVersionedIdToObjectId(targetId);
if (objectId != null && lwM2MClient.isValidObjectVersion(targetId)) {
LwM2mPath resultIds = new LwM2mPath(objectId);
Set<Observation> observations = context.getServer().getObservationService().getObservations(lwM2MClient.getRegistration());
if (observations.stream().noneMatch(observation -> observation.getPath().equals(resultIds))) {
ObserveRequest request;
if (resultIds.isResource()) {
request = new ObserveRequest(contentFormat, resultIds.getObjectId(), resultIds.getObjectInstanceId(), resultIds.getResourceId());
} else if (resultIds.isObjectInstance()) {
request = new ObserveRequest(contentFormat, resultIds.getObjectId(), resultIds.getObjectInstanceId());
} else {
request = new ObserveRequest(contentFormat, resultIds.getObjectId());
}
log.info("[{}] Send observation: {}.", lwM2MClient.getEndpoint(), targetId);
sendRequest(lwM2MClient, request, timeout);
}
}
}
public void sendDiscoverRequest(LwM2mClient lwM2MClient, String targetId, Long timeout) {
String objectId = fromVersionedIdToObjectId(targetId);
if (objectId != null && lwM2MClient.isValidObjectVersion(targetId)) {
sendRequest(lwM2MClient, new DiscoverRequest(objectId), timeout);
}
}
public void sendWriteAttributesRequest(LwM2mClient lwM2MClient, String targetId, ObjectAttributes params, Long timeout) {
String objectId = fromVersionedIdToObjectId(targetId);
if (objectId != null && lwM2MClient.isValidObjectVersion(targetId) && params != null) {
List<Attribute> 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);
sendRequest(lwM2MClient, new WriteAttributesRequest(objectId, attributeSet), timeout);
}
}
private <T> void addAttribute(List<Attribute> attributes, String attributeName, T value) {
addAttribute(attributes, attributeName, value, null, null);
}
private <T> void addAttribute(List<Attribute> attributes, String attributeName, T value, Function<T, ?> converter) {
addAttribute(attributes, attributeName, value, null, converter);
}
private <T> void addAttribute(List<Attribute> attributes, String attributeName, T value, Predicate<T> filter, Function<T, ?> converter) {
if (value != null && ((filter == null) || filter.test(value))) {
attributes.add(new Attribute(attributeName, converter != null ? converter.apply(value) : value));
}
}
public void sendAllRequest(LwM2mClient lwM2MClient, String targetIdVer, LwM2mTypeOper typeOper, Object params, long timeoutInMs, LwM2mClientRpcRequest lwm2mClientRpcRequest) {
sendAllRequest(lwM2MClient, targetIdVer, typeOper, lwM2MClient.getDefaultContentFormat(), params, timeoutInMs, lwm2mClientRpcRequest);
}
public void sendAllRequest(LwM2mClient lwM2MClient, String targetIdVer, LwM2mTypeOper typeOper,
ContentFormat contentFormat, Object params, long timeoutInMs, LwM2mClientRpcRequest lwm2mClientRpcRequest) {
Registration registration = lwM2MClient.getRegistration();
try {
String target = convertPathFromIdVerToObjectId(targetIdVer);
if(contentFormat == null){
String target = fromVersionedIdToObjectId(targetIdVer);
if (contentFormat == null) {
contentFormat = ContentFormat.DEFAULT;
}
LwM2mPath resultIds = target != null ? new LwM2mPath(target) : null;
if (!OBSERVE_CANCEL.name().equals(typeOper.name()) && resultIds != null && registration != null && resultIds.getObjectId() >= 0 && lwM2MClient != null) {
if (!OBSERVE_CANCEL.name().equals(typeOper.name()) && resultIds != null && registration != null && resultIds.getObjectId() >= 0) {
if (lwM2MClient.isValidObjectVersion(targetIdVer)) {
timeoutInMs = timeoutInMs > 0 ? timeoutInMs : DEFAULT_TIMEOUT;
SimpleDownlinkRequest request = createRequest(registration, lwM2MClient, typeOper, contentFormat, target,
targetIdVer, resultIds, params, lwm2mClientRpcRequest);
if (request != null) {
try {
this.sendRequest(registration, lwM2MClient, request, timeoutInMs, lwm2mClientRpcRequest);
this.sendRequest(lwM2MClient, request, timeoutInMs, lwm2mClientRpcRequest);
} catch (ClientSleepingException e) {
SimpleDownlinkRequest finalRequest = request;
long finalTimeoutInMs = timeoutInMs;
LwM2mClientRpcRequest finalRpcRequest = lwm2mClientRpcRequest;
lwM2MClient.getQueuedRequests().add(() -> sendRequest(registration, lwM2MClient, finalRequest, finalTimeoutInMs, finalRpcRequest));
lwM2MClient.getQueuedRequests().add(() -> sendRequest(lwM2MClient, finalRequest, finalTimeoutInMs, finalRpcRequest));
} catch (Exception e) {
log.error("[{}] [{}] [{}] Failed to send downlink.", registration.getEndpoint(), targetIdVer, typeOper.name(), e);
}
@ -222,8 +309,8 @@ public class LwM2mTransportRequest {
}
private SimpleDownlinkRequest createRequest(Registration registration, LwM2mClient lwM2MClient, LwM2mTypeOper typeOper,
ContentFormat contentFormat, String target, String targetIdVer,
LwM2mPath resultIds, Object params, LwM2mClientRpcRequest rpcRequest) {
ContentFormat contentFormat, String target, String targetIdVer,
LwM2mPath resultIds, Object params, LwM2mClientRpcRequest rpcRequest) {
SimpleDownlinkRequest request = null;
switch (typeOper) {
case READ:
@ -320,15 +407,18 @@ public class LwM2mTransportRequest {
return request;
}
/**
* @param registration -
* @param request -
* @param timeoutInMs -
*/
private void sendRequest(LwM2mClient lwM2MClient, SimpleDownlinkRequest request, long timeoutInMs) {
try {
sendRequest(lwM2MClient, request, timeoutInMs, null);
} catch (ClientSleepingException e) {
//TODO: this may cause infinite loop / memory leak.
lwM2MClient.getQueuedRequests().add(() -> sendRequest(lwM2MClient, request, timeoutInMs, null));
}
}
@SuppressWarnings({"error sendRequest"})
private void sendRequest(Registration registration, LwM2mClient lwM2MClient, SimpleDownlinkRequest request,
long timeoutInMs, LwM2mClientRpcRequest rpcRequest) {
private void sendRequest(LwM2mClient lwM2MClient, SimpleDownlinkRequest request, long timeoutInMs, LwM2mClientRpcRequest rpcRequest) {
Registration registration = lwM2MClient.getRegistration();
context.getServer().send(registration, request, timeoutInMs, (ResponseCallback<?>) response -> {
if (!lwM2MClient.isInit()) {
@ -455,8 +545,8 @@ public class LwM2mTransportRequest {
/**
* processing a response from a client
*
* @param path -
* @param response -
* @param path -
* @param response -
*/
private void sendResponse(LwM2mClient lwM2mClient, String path, LwM2mResponse response,
SimpleDownlinkRequest request, LwM2mClientRpcRequest rpcRequest) {
@ -550,8 +640,7 @@ public class LwM2mTransportRequest {
if (rpcRequest != null) {
rpcRequest.setInfoMsg(msg);
}
}
else if (rpcRequest != null) {
} else if (rpcRequest != null) {
handler.sentRpcResponse(rpcRequest, response.getCode().getName(), msg, LOG_LW2M_INFO);
}
}
@ -610,4 +699,5 @@ public class LwM2mTransportRequest {
handler.sentRpcResponse(rpcRequest, CONTENT.name(), null, LOG_LW2M_INFO);
}
}
}

167
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportUtil.java

@ -16,13 +16,9 @@
package org.thingsboard.server.transport.lwm2m.server;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Sets;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.JsonSyntaxException;
import com.google.gson.reflect.TypeToken;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.leshan.core.attributes.Attribute;
@ -42,17 +38,17 @@ import org.eclipse.leshan.core.util.Hex;
import org.eclipse.leshan.server.registration.Registration;
import org.nustaq.serialization.FSTConfiguration;
import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.data.DeviceTransportType;
import org.thingsboard.server.common.data.device.data.lwm2m.BootstrapConfiguration;
import org.thingsboard.server.common.data.device.profile.DeviceProfileTransportConfiguration;
import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTransportConfiguration;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.ota.OtaPackageKey;
import org.thingsboard.server.common.data.ota.OtaPackageType;
import org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus;
import org.thingsboard.server.common.data.ota.OtaPackageUtil;
import org.thingsboard.server.common.transport.TransportServiceCallback;
import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientProfile;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
@ -60,7 +56,6 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import static org.eclipse.leshan.core.attributes.Attribute.DIMENSION;
@ -379,7 +374,7 @@ public class LwM2mTransportUtil {
switch (updateResultFw) {
case INITIAL:
return equalsFwSateToFirmwareUpdateStatus(stateFw);
case UPDATE_SUCCESSFULLY:
case UPDATE_SUCCESSFULLY:
return UPDATED;
case NOT_ENOUGH:
case OUT_OFF_MEMORY:
@ -399,7 +394,7 @@ public class LwM2mTransportUtil {
switch (updateResultFw) {
case INITIAL:
return VERIFIED;
case UPDATE_SUCCESSFULLY:
case UPDATE_SUCCESSFULLY:
return UPDATED;
case NOT_ENOUGH:
case OUT_OFF_MEMORY:
@ -695,26 +690,23 @@ public class LwM2mTransportUtil {
}
}
public static LwM2mOtaConvert convertOtaUpdateValueToString (String pathIdVer, Object value, ResourceModel.Type currentType) {
String path = convertPathFromIdVerToObjectId(pathIdVer);
public static LwM2mOtaConvert convertOtaUpdateValueToString(String pathIdVer, Object value, ResourceModel.Type currentType) {
String path = fromVersionedIdToObjectId(pathIdVer);
LwM2mOtaConvert lwM2mOtaConvert = new LwM2mOtaConvert();
if (path != null) {
if (FW_STATE_ID.equals(path)) {
lwM2mOtaConvert.setCurrentType(STRING);
lwM2mOtaConvert.setValue(StateFw.fromStateFwByCode(((Long) value).intValue()).type);
return lwM2mOtaConvert;
}
else if (FW_RESULT_ID.equals(path)) {
} else if (FW_RESULT_ID.equals(path)) {
lwM2mOtaConvert.setCurrentType(STRING);
lwM2mOtaConvert.setValue(UpdateResultFw.fromUpdateResultFwByCode(((Long) value).intValue()).type);
return lwM2mOtaConvert;
}
else if (SW_UPDATE_STATE_ID.equals(path)) {
} else if (SW_UPDATE_STATE_ID.equals(path)) {
lwM2mOtaConvert.setCurrentType(STRING);
lwM2mOtaConvert.setValue(UpdateStateSw.fromUpdateStateSwByCode(((Long) value).intValue()).type);
return lwM2mOtaConvert;
}
else if (SW_RESULT_ID.equals(path)) {
} else if (SW_RESULT_ID.equals(path)) {
lwM2mOtaConvert.setCurrentType(STRING);
lwM2mOtaConvert.setValue(UpdateResultSw.fromUpdateResultSwByCode(((Long) value).intValue()).type);
return lwM2mOtaConvert;
@ -738,113 +730,32 @@ public class LwM2mTransportUtil {
return null;
}
public static LwM2mClientProfile getNewProfileParameters(JsonObject profilesConfigData, TenantId tenantId) {
LwM2mClientProfile lwM2MClientProfile = new LwM2mClientProfile();
lwM2MClientProfile.setTenantId(tenantId);
lwM2MClientProfile.setPostClientLwM2mSettings(profilesConfigData.get(CLIENT_LWM2M_SETTINGS).getAsJsonObject());
lwM2MClientProfile.setPostKeyNameProfile(profilesConfigData.get(OBSERVE_ATTRIBUTE_TELEMETRY).getAsJsonObject().get(KEY_NAME).getAsJsonObject());
lwM2MClientProfile.setPostAttributeProfile(profilesConfigData.get(OBSERVE_ATTRIBUTE_TELEMETRY).getAsJsonObject().get(ATTRIBUTE).getAsJsonArray());
lwM2MClientProfile.setPostTelemetryProfile(profilesConfigData.get(OBSERVE_ATTRIBUTE_TELEMETRY).getAsJsonObject().get(TELEMETRY).getAsJsonArray());
lwM2MClientProfile.setPostObserveProfile(profilesConfigData.get(OBSERVE_ATTRIBUTE_TELEMETRY).getAsJsonObject().get(OBSERVE_LWM2M).getAsJsonArray());
lwM2MClientProfile.setPostAttributeLwm2mProfile(profilesConfigData.get(OBSERVE_ATTRIBUTE_TELEMETRY).getAsJsonObject().get(ATTRIBUTE_LWM2M).getAsJsonObject());
return lwM2MClientProfile;
}
/**
* @return deviceProfileBody with Observe&Attribute&Telemetry From Thingsboard
* Example:
* property: {"clientLwM2mSettings": {
* clientUpdateValueAfterConnect: false;
* }
* property: "observeAttr"
* {"keyName": {
* "/3/0/1": "modelNumber",
* "/3/0/0": "manufacturer",
* "/3/0/2": "serialNumber"
* },
* "attribute":["/2/0/1","/3/0/9"],
* "telemetry":["/1/0/1","/2/0/1","/6/0/1"],
* "observe":["/2/0","/2/0/0","/4/0/2"]}
* "attributeLwm2m": {"/3_1.0": {"ver": "currentTimeTest11"},
* "/3_1.0/0": {"gt": 17},
* "/3_1.0/0/9": {"pmax": 45}, "/3_1.2": {ver": "3_1.2"}}
*/
//TODO: refactor this to valid jackson code instead of parsing manually.
public static LwM2mClientProfile toLwM2MClientProfile(DeviceProfile deviceProfile) {
// if (((Lwm2mDeviceProfileTransportConfiguration) deviceProfile.getProfileData().getTransportConfiguration()).getProperties().size() > 0) {
// Object profile = ((Lwm2mDeviceProfileTransportConfiguration) deviceProfile.getProfileData().getTransportConfiguration()).getProperties();
// try {
// ObjectMapper mapper = new ObjectMapper();
// String profileStr = mapper.writeValueAsString(profile);
// JsonObject profileJson = (profileStr != null) ? validateJson(profileStr) : null;
// return getValidateCredentialsBodyFromThingsboard(profileJson) ? LwM2mTransportUtil.getNewProfileParameters(profileJson, deviceProfile.getTenantId()) : null;
// } catch (IOException e) {
// log.error("", e);
// }
// }
return null;
}
public static JsonObject getBootstrapParametersFromThingsboard(DeviceProfile deviceProfile) {
// if (deviceProfile != null && ((Lwm2mDeviceProfileTransportConfiguration) deviceProfile.getProfileData().getTransportConfiguration()).getProperties().size() > 0) {
// Object bootstrap = ((Lwm2mDeviceProfileTransportConfiguration) deviceProfile.getProfileData().getTransportConfiguration()).getProperties();
// try {
// ObjectMapper mapper = new ObjectMapper();
// String bootstrapStr = mapper.writeValueAsString(bootstrap);
// JsonObject objectMsg = (bootstrapStr != null) ? validateJson(bootstrapStr) : null;
// return (getValidateBootstrapProfileFromThingsboard(objectMsg)) ? objectMsg.get(BOOTSTRAP).getAsJsonObject() : null;
// } catch (IOException e) {
// log.error("", e);
// }
// }
return null;
}
private static boolean getValidateCredentialsBodyFromThingsboard(JsonObject objectMsg) {
return (objectMsg != null &&
!objectMsg.isJsonNull() &&
objectMsg.has(CLIENT_LWM2M_SETTINGS) &&
!objectMsg.get(CLIENT_LWM2M_SETTINGS).isJsonNull() &&
objectMsg.get(CLIENT_LWM2M_SETTINGS).isJsonObject() &&
objectMsg.has(OBSERVE_ATTRIBUTE_TELEMETRY) &&
!objectMsg.get(OBSERVE_ATTRIBUTE_TELEMETRY).isJsonNull() &&
objectMsg.get(OBSERVE_ATTRIBUTE_TELEMETRY).isJsonObject() &&
objectMsg.get(OBSERVE_ATTRIBUTE_TELEMETRY).getAsJsonObject().has(KEY_NAME) &&
!objectMsg.get(OBSERVE_ATTRIBUTE_TELEMETRY).getAsJsonObject().get(KEY_NAME).isJsonNull() &&
objectMsg.get(OBSERVE_ATTRIBUTE_TELEMETRY).getAsJsonObject().get(KEY_NAME).isJsonObject() &&
objectMsg.get(OBSERVE_ATTRIBUTE_TELEMETRY).getAsJsonObject().has(ATTRIBUTE) &&
!objectMsg.get(OBSERVE_ATTRIBUTE_TELEMETRY).getAsJsonObject().get(ATTRIBUTE).isJsonNull() &&
objectMsg.get(OBSERVE_ATTRIBUTE_TELEMETRY).getAsJsonObject().get(ATTRIBUTE).isJsonArray() &&
objectMsg.get(OBSERVE_ATTRIBUTE_TELEMETRY).getAsJsonObject().has(TELEMETRY) &&
!objectMsg.get(OBSERVE_ATTRIBUTE_TELEMETRY).getAsJsonObject().get(TELEMETRY).isJsonNull() &&
objectMsg.get(OBSERVE_ATTRIBUTE_TELEMETRY).getAsJsonObject().get(TELEMETRY).isJsonArray() &&
objectMsg.get(OBSERVE_ATTRIBUTE_TELEMETRY).getAsJsonObject().has(OBSERVE_LWM2M) &&
!objectMsg.get(OBSERVE_ATTRIBUTE_TELEMETRY).getAsJsonObject().get(OBSERVE_LWM2M).isJsonNull() &&
objectMsg.get(OBSERVE_ATTRIBUTE_TELEMETRY).getAsJsonObject().get(OBSERVE_LWM2M).isJsonArray() &&
objectMsg.get(OBSERVE_ATTRIBUTE_TELEMETRY).getAsJsonObject().has(ATTRIBUTE_LWM2M) &&
!objectMsg.get(OBSERVE_ATTRIBUTE_TELEMETRY).getAsJsonObject().get(ATTRIBUTE_LWM2M).isJsonNull() &&
objectMsg.get(OBSERVE_ATTRIBUTE_TELEMETRY).getAsJsonObject().get(ATTRIBUTE_LWM2M).isJsonObject());
// public static LwM2mClientProfile getNewProfileParameters(JsonObject profilesConfigData, TenantId tenantId) {
// LwM2mClientProfile lwM2MClientProfile = new LwM2mClientProfile();
// lwM2MClientProfile.setTenantId(tenantId);
// lwM2MClientProfile.setPostClientLwM2mSettings(profilesConfigData.get(CLIENT_LWM2M_SETTINGS).getAsJsonObject());
// lwM2MClientProfile.setPostKeyNameProfile(profilesConfigData.get(OBSERVE_ATTRIBUTE_TELEMETRY).getAsJsonObject().get(KEY_NAME).getAsJsonObject());
// lwM2MClientProfile.setPostAttributeProfile(profilesConfigData.get(OBSERVE_ATTRIBUTE_TELEMETRY).getAsJsonObject().get(ATTRIBUTE).getAsJsonArray());
// lwM2MClientProfile.setPostTelemetryProfile(profilesConfigData.get(OBSERVE_ATTRIBUTE_TELEMETRY).getAsJsonObject().get(TELEMETRY).getAsJsonArray());
// lwM2MClientProfile.setPostObserveProfile(profilesConfigData.get(OBSERVE_ATTRIBUTE_TELEMETRY).getAsJsonObject().get(OBSERVE_LWM2M).getAsJsonArray());
// lwM2MClientProfile.setPostAttributeLwm2mProfile(profilesConfigData.get(OBSERVE_ATTRIBUTE_TELEMETRY).getAsJsonObject().get(ATTRIBUTE_LWM2M).getAsJsonObject());
// return lwM2MClientProfile;
// }
public static Lwm2mDeviceProfileTransportConfiguration toLwM2MClientProfile(DeviceProfile deviceProfile) {
DeviceProfileTransportConfiguration transportConfiguration = deviceProfile.getProfileData().getTransportConfiguration();
if (transportConfiguration.getType().equals(DeviceTransportType.LWM2M)) {
return (Lwm2mDeviceProfileTransportConfiguration) transportConfiguration;
} else {
log.warn("[{}] Received profile with invalid transport configuration: {}", deviceProfile.getId(), deviceProfile.getProfileData().getTransportConfiguration());
throw new IllegalArgumentException("Received profile with invalid transport configuration: " + transportConfiguration.getType());
}
}
private static boolean getValidateBootstrapProfileFromThingsboard(JsonObject objectMsg) {
return (objectMsg != null &&
!objectMsg.isJsonNull() &&
objectMsg.has(BOOTSTRAP) &&
objectMsg.get(BOOTSTRAP).isJsonObject() &&
!objectMsg.get(BOOTSTRAP).isJsonNull() &&
objectMsg.get(BOOTSTRAP).getAsJsonObject().has(SERVERS) &&
!objectMsg.get(BOOTSTRAP).getAsJsonObject().get(SERVERS).isJsonNull() &&
objectMsg.get(BOOTSTRAP).getAsJsonObject().get(SERVERS).isJsonObject() &&
objectMsg.get(BOOTSTRAP).getAsJsonObject().has(BOOTSTRAP_SERVER) &&
!objectMsg.get(BOOTSTRAP).getAsJsonObject().get(BOOTSTRAP_SERVER).isJsonNull() &&
objectMsg.get(BOOTSTRAP).getAsJsonObject().get(BOOTSTRAP_SERVER).isJsonObject() &&
objectMsg.get(BOOTSTRAP).getAsJsonObject().has(LWM2M_SERVER) &&
!objectMsg.get(BOOTSTRAP).getAsJsonObject().get(LWM2M_SERVER).isJsonNull() &&
objectMsg.get(BOOTSTRAP).getAsJsonObject().get(LWM2M_SERVER).isJsonObject());
public static BootstrapConfiguration getBootstrapParametersFromThingsboard(DeviceProfile deviceProfile) {
return toLwM2MClientProfile(deviceProfile).getBootstrap();
}
public static JsonObject validateJson(String jsonStr) {
JsonObject object = null;
if (jsonStr != null && !jsonStr.isEmpty()) {
@ -901,8 +812,11 @@ public class LwM2mTransportUtil {
};
}
public static String convertPathFromIdVerToObjectId(String pathIdVer) {
public static String fromVersionedIdToObjectId(String pathIdVer) {
try {
if(pathIdVer == null) {
return null;
}
String[] keyArray = pathIdVer.split(LWM2M_SEPARATOR_PATH);
if (keyArray.length > 1 && keyArray[1].split(LWM2M_SEPARATOR_KEY).length == 2) {
keyArray[1] = keyArray[1].split(LWM2M_SEPARATOR_KEY)[0];
@ -911,7 +825,8 @@ public class LwM2mTransportUtil {
return pathIdVer;
}
} catch (Exception e) {
return null;
log.warn("Issue converting path with version [{}] to path without version: ", pathIdVer, e);
throw new RuntimeException(e);
}
}
@ -1025,12 +940,6 @@ public class LwM2mTransportUtil {
return attributeLists.toArray(Attribute[]::new);
}
public static Set<String> convertJsonArrayToSet(JsonArray jsonArray) {
List<String> attributeListOld = new Gson().fromJson(jsonArray, new TypeToken<List<String>>() {
}.getType());
return Sets.newConcurrentHashSet(attributeListOld);
}
public static ResourceModel.Type equalsResourceTypeGetSimpleName(Object value) {
switch (value.getClass().getSimpleName()) {
case "Double":

2
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mVersionedModelProvider.java

@ -72,7 +72,7 @@ public class LwM2mVersionedModelProvider implements LwM2mModelProvider {
public DynamicModel(Registration registration) {
this.registration = registration;
this.tenantId = lwM2mClientContext.getProfile(registration).getTenantId();
this.tenantId = lwM2mClientContext.getClientByEndpoint(registration.getEndpoint()).getTenantId();
}
@Override

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

@ -32,6 +32,7 @@ import org.eclipse.leshan.server.registration.Registration;
import org.eclipse.leshan.server.security.SecurityInfo;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.ota.OtaPackageType;
import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse;
import org.thingsboard.server.gen.transport.TransportProtos.SessionInfoProto;
@ -58,7 +59,7 @@ import static org.eclipse.leshan.core.model.ResourceModel.Type.OPAQUE;
import static org.eclipse.leshan.core.model.ResourceModel.Type.STRING;
import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_PATH;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.TRANSPORT_DEFAULT_LWM2M_VERSION;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertPathFromIdVerToObjectId;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.fromVersionedIdToObjectId;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertPathFromObjectIdToIdVer;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.equalsResourceTypeGetSimpleName;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.getVerFromPathIdVerOrId;
@ -92,6 +93,8 @@ public class LwM2mClient implements Cloneable {
@Getter
private SecurityInfo securityInfo;
@Getter
private TenantId tenantId;
@Getter
private UUID deviceId;
@Getter
private SessionInfoProto session;
@ -127,19 +130,17 @@ public class LwM2mClient implements Cloneable {
this.state = LwM2MClientState.CREATED;
}
public void init(String identity, SecurityInfo securityInfo, ValidateDeviceCredentialsResponse credentials, UUID profileId, UUID sessionId) {
public void init(String identity, SecurityInfo securityInfo, ValidateDeviceCredentialsResponse credentials, UUID sessionId) {
this.identity = identity;
this.securityInfo = securityInfo;
this.credentials = credentials;
this.profileId = profileId;
this.init = false;
if (this.credentials != null && this.credentials.hasDeviceInfo()) {
this.session = createSession(nodeId, sessionId, credentials);
this.deviceId = new UUID(session.getDeviceIdMSB(), session.getDeviceIdLSB());
this.profileId = new UUID(session.getDeviceProfileIdMSB(), session.getDeviceProfileIdLSB());
this.deviceName = session.getDeviceName();
this.deviceProfileName = session.getDeviceType();
}
this.session = createSession(nodeId, sessionId, credentials);
this.tenantId = new TenantId(new UUID(session.getTenantIdMSB(), session.getTenantIdLSB()));
this.deviceId = new UUID(session.getDeviceIdMSB(), session.getDeviceIdLSB());
this.profileId = new UUID(session.getDeviceProfileIdMSB(), session.getDeviceProfileIdLSB());
this.deviceName = session.getDeviceName();
this.deviceProfileName = session.getDeviceType();
}
public void lock() {
@ -198,7 +199,7 @@ public class LwM2mClient implements Cloneable {
this.resources.get(pathRezIdVer).setLwM2mResource(rez);
return true;
} else {
LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(pathRezIdVer));
LwM2mPath pathIds = new LwM2mPath(fromVersionedIdToObjectId(pathRezIdVer));
ResourceModel resourceModel = modelProvider.getObjectModel(registration).getResourceModel(pathIds.getObjectId(), pathIds.getResourceId());
if (resourceModel != null) {
this.resources.put(pathRezIdVer, new ResourceValue(rez, resourceModel));
@ -226,7 +227,7 @@ public class LwM2mClient implements Cloneable {
}
public String getRezIdByResourceNameAndObjectInstanceId(String resourceName, String pathObjectInstanceIdVer, LwM2mModelProvider modelProvider) {
LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(pathObjectInstanceIdVer));
LwM2mPath pathIds = new LwM2mPath(fromVersionedIdToObjectId(pathObjectInstanceIdVer));
if (pathIds.isObjectInstance()) {
Set<Integer> rezIds = modelProvider.getObjectModel(registration)
.getObjectModel(pathIds.getObjectId()).resources.entrySet()
@ -240,7 +241,7 @@ public class LwM2mClient implements Cloneable {
}
public ResourceModel getResourceModel(String pathIdVer, LwM2mModelProvider modelProvider) {
LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(pathIdVer));
LwM2mPath pathIds = new LwM2mPath(fromVersionedIdToObjectId(pathIdVer));
String verSupportedObject = registration.getSupportedObject().get(pathIds.getObjectId());
String verRez = getVerFromPathIdVerOrId(pathIdVer);
return verRez == null || verRez.equals(verSupportedObject) ? modelProvider.getObjectModel(registration)
@ -248,7 +249,7 @@ public class LwM2mClient implements Cloneable {
}
public ObjectModel getObjectModel(String pathIdVer, LwM2mModelProvider modelProvider) {
LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(pathIdVer));
LwM2mPath pathIds = new LwM2mPath(fromVersionedIdToObjectId(pathIdVer));
String verSupportedObject = registration.getSupportedObject().get(pathIds.getObjectId());
String verRez = getVerFromPathIdVerOrId(pathIdVer);
return verRez == null || verRez.equals(verSupportedObject) ? modelProvider.getObjectModel(registration)
@ -290,13 +291,13 @@ public class LwM2mClient implements Cloneable {
} else {
return String.format("LwM2mSingleResource [id=%s, value=%s, type=%s]", lwM2mResource.getId(),
converter.convertValue(lwM2mResource.getValue(),
OPAQUE, STRING, new LwM2mPath(convertPathFromIdVerToObjectId(pathIdVer))), lwM2mResource.getType().name());
OPAQUE, STRING, new LwM2mPath(fromVersionedIdToObjectId(pathIdVer))), lwM2mResource.getType().name());
}
}
public Collection<LwM2mResource> getNewResourceForInstance(String pathRezIdVer, Object params, LwM2mModelProvider modelProvider,
LwM2mValueConverterImpl converter) {
LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(pathRezIdVer));
LwM2mPath pathIds = new LwM2mPath(fromVersionedIdToObjectId(pathRezIdVer));
Collection<LwM2mResource> resources = ConcurrentHashMap.newKeySet();
Map<Integer, ResourceModel> resourceModels = modelProvider.getObjectModel(registration)
.getObjectModel(pathIds.getObjectId()).resources;
@ -312,7 +313,7 @@ public class LwM2mClient implements Cloneable {
public Collection<LwM2mResource> getNewResourcesForInstance(String pathRezIdVer, Object params, LwM2mModelProvider modelProvider,
LwM2mValueConverterImpl converter) {
LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(pathRezIdVer));
LwM2mPath pathIds = new LwM2mPath(fromVersionedIdToObjectId(pathRezIdVer));
Collection<LwM2mResource> resources = ConcurrentHashMap.newKeySet();
Map<Integer, ResourceModel> resourceModels = modelProvider.getObjectModel(registration)
.getObjectModel(pathIds.getObjectId()).resources;
@ -328,7 +329,7 @@ public class LwM2mClient implements Cloneable {
}
public boolean isValidObjectVersion(String path) {
LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(path));
LwM2mPath pathIds = new LwM2mPath(fromVersionedIdToObjectId(path));
String verSupportedObject = registration.getSupportedObject().get(pathIds.getObjectId());
String verRez = getVerFromPathIdVerOrId(path);
return verRez == null ? TRANSPORT_DEFAULT_LWM2M_VERSION.equals(verSupportedObject) : verRez.equals(verSupportedObject);
@ -341,7 +342,7 @@ public class LwM2mClient implements Cloneable {
public void deleteResources(String pathIdVer, LwM2mModelProvider modelProvider) {
Set<String> key = getKeysEqualsIdVer(pathIdVer);
key.forEach(pathRez -> {
LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(pathRez));
LwM2mPath pathIds = new LwM2mPath(fromVersionedIdToObjectId(pathRez));
ResourceModel resourceModel = modelProvider.getObjectModel(registration).getResourceModel(pathIds.getObjectId(), pathIds.getResourceId());
if (resourceModel != null) {
this.resources.get(pathRez).setResourceModel(resourceModel);
@ -361,7 +362,7 @@ public class LwM2mClient implements Cloneable {
}
private void saveResourceModel(String pathRez, LwM2mModelProvider modelProvider) {
LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(pathRez));
LwM2mPath pathIds = new LwM2mPath(fromVersionedIdToObjectId(pathRez));
ResourceModel resourceModel = modelProvider.getObjectModel(registration).getResourceModel(pathIds.getObjectId(), pathIds.getResourceId());
this.resources.get(pathRez).setResourceModel(resourceModel);
}
@ -395,16 +396,16 @@ public class LwM2mClient implements Cloneable {
public LwM2mFwSwUpdate getFwUpdate (LwM2mClientContext clientContext) {
if (this.fwUpdate == null) {
LwM2mClientProfile lwM2mClientProfile = clientContext.getProfile(this.getProfileId());
this.fwUpdate = new LwM2mFwSwUpdate(this, OtaPackageType.FIRMWARE, lwM2mClientProfile.getFwUpdateStrategy());
var profile = clientContext.getProfile(this.getProfileId());
this.fwUpdate = new LwM2mFwSwUpdate(this, OtaPackageType.FIRMWARE, profile.getClientLwM2mSettings().getFwUpdateStrategy());
}
return this.fwUpdate;
}
public LwM2mFwSwUpdate getSwUpdate (LwM2mClientContext clientContext) {
if (this.swUpdate == null) {
LwM2mClientProfile lwM2mClientProfile = clientContext.getProfile(this.getProfileId());
this.swUpdate = new LwM2mFwSwUpdate(this, OtaPackageType.SOFTWARE, lwM2mClientProfile.getSwUpdateStrategy());
var profile = clientContext.getProfile(this.getProfileId());
this.swUpdate = new LwM2mFwSwUpdate(this, OtaPackageType.SOFTWARE, profile.getClientLwM2mSettings().getSwUpdateStrategy());
}
return this.fwUpdate;
}

14
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientContext.java

@ -17,11 +17,12 @@ package org.thingsboard.server.transport.lwm2m.server.client;
import org.eclipse.leshan.server.registration.Registration;
import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTransportConfiguration;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse;
import org.thingsboard.server.gen.transport.TransportProtos;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
@ -41,15 +42,12 @@ public interface LwM2mClientContext {
Collection<LwM2mClient> getLwM2mClients();
Map<UUID, LwM2mClientProfile> getProfiles();
//TODO: replace UUID with DeviceProfileId
Lwm2mDeviceProfileTransportConfiguration getProfile(UUID profileUuId);
LwM2mClientProfile getProfile(UUID profileUuId);
Lwm2mDeviceProfileTransportConfiguration getProfile(Registration registration);
LwM2mClientProfile getProfile(Registration registration);
Map<UUID, LwM2mClientProfile> setProfiles(Map<UUID, LwM2mClientProfile> profiles);
LwM2mClientProfile profileUpdate(DeviceProfile deviceProfile);
Lwm2mDeviceProfileTransportConfiguration profileUpdate(DeviceProfile deviceProfile);
Set<String> getSupportedIdVerInClient(LwM2mClient registration);

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

@ -21,6 +21,7 @@ import org.eclipse.leshan.core.node.LwM2mPath;
import org.eclipse.leshan.server.registration.Registration;
import org.springframework.stereotype.Service;
import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTransportConfiguration;
import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse;
import org.thingsboard.server.gen.transport.TransportProtos;
import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;
@ -50,7 +51,7 @@ public class LwM2mClientContextImpl implements LwM2mClientContext {
private final TbEditableSecurityStore securityStore;
private final Map<String, LwM2mClient> lwM2mClientsByEndpoint = new ConcurrentHashMap<>();
private final Map<String, LwM2mClient> lwM2mClientsByRegistrationId = new ConcurrentHashMap<>();
private Map<UUID, LwM2mClientProfile> profiles = new ConcurrentHashMap<>();
private final Map<UUID, Lwm2mDeviceProfileTransportConfiguration> profiles = new ConcurrentHashMap<>();
@Override
public LwM2mClient getClientByEndpoint(String endpoint) {
@ -67,11 +68,11 @@ public class LwM2mClientContextImpl implements LwM2mClientContext {
TbLwM2MSecurityInfo securityInfo = securityStore.getTbLwM2MSecurityInfoByEndpoint(lwM2MClient.getEndpoint());
if (securityInfo.getSecurityMode() != null) {
if (securityInfo.getDeviceProfile() != null) {
UUID profileUuid = profileUpdate(securityInfo.getDeviceProfile()) != null ? securityInfo.getDeviceProfile().getUuidId() : null;
profileUpdate(securityInfo.getDeviceProfile());
if (securityInfo.getSecurityInfo() != null) {
lwM2MClient.init(securityInfo.getSecurityInfo().getIdentity(), securityInfo.getSecurityInfo(), securityInfo.getMsg(), profileUuid, UUID.randomUUID());
lwM2MClient.init(securityInfo.getSecurityInfo().getIdentity(), securityInfo.getSecurityInfo(), securityInfo.getMsg(), UUID.randomUUID());
} else if (NO_SEC.equals(securityInfo.getSecurityMode())) {
lwM2MClient.init(null, null, securityInfo.getMsg(), profileUuid, UUID.randomUUID());
lwM2MClient.init(null, null, securityInfo.getMsg(), UUID.randomUUID());
} else {
throw new RuntimeException(String.format("Registration failed: device %s not found.", lwM2MClient.getEndpoint()));
}
@ -157,7 +158,7 @@ public class LwM2mClientContextImpl implements LwM2mClientContext {
@Override
public void registerClient(Registration registration, ValidateDeviceCredentialsResponse credentials) {
LwM2mClient client = getClientByEndpoint(registration.getEndpoint());
client.init(null, null, credentials, credentials.getDeviceProfile().getUuidId(), UUID.randomUUID());
client.init(null, null, credentials, UUID.randomUUID());
lwM2mClientsByRegistrationId.put(registration.getId(), client);
profileUpdate(credentials.getDeviceProfile());
}
@ -168,35 +169,20 @@ public class LwM2mClientContextImpl implements LwM2mClientContext {
}
@Override
public Map<UUID, LwM2mClientProfile> getProfiles() {
return profiles;
}
@Override
public LwM2mClientProfile getProfile(UUID profileId) {
public Lwm2mDeviceProfileTransportConfiguration getProfile(UUID profileId) {
return profiles.get(profileId);
}
@Override
public LwM2mClientProfile getProfile(Registration registration) {
return this.getProfiles().get(getClientByEndpoint(registration.getEndpoint()).getProfileId());
public Lwm2mDeviceProfileTransportConfiguration getProfile(Registration registration) {
return profiles.get(getClientByEndpoint(registration.getEndpoint()).getProfileId());
}
@Override
public Map<UUID, LwM2mClientProfile> setProfiles(Map<UUID, LwM2mClientProfile> profiles) {
return this.profiles = profiles;
}
@Override
public LwM2mClientProfile profileUpdate(DeviceProfile deviceProfile) {
LwM2mClientProfile lwM2MClientProfile = deviceProfile != null ?
LwM2mTransportUtil.toLwM2MClientProfile(deviceProfile) : null;
if (lwM2MClientProfile != null) {
profiles.put(deviceProfile.getUuidId(), lwM2MClientProfile);
return lwM2MClientProfile;
} else {
return null;
}
public Lwm2mDeviceProfileTransportConfiguration profileUpdate(DeviceProfile deviceProfile) {
Lwm2mDeviceProfileTransportConfiguration lwM2MClientProfile = LwM2mTransportUtil.toLwM2MClientProfile(deviceProfile);
profiles.put(deviceProfile.getUuidId(), lwM2MClientProfile);
return lwM2MClientProfile;
}
@Override

113
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientProfile.java

@ -1,113 +0,0 @@
/**
* 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.client;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import lombok.Data;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2MClientStrategy;
import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2MFirmwareUpdateStrategy;
import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2MSoftwareUpdateStrategy;
@Data
public class LwM2mClientProfile {
private final String clientStrategyStr = "clientStrategy";
private final String fwUpdateStrategyStr = "fwUpdateStrategy";
private final String swUpdateStrategyStr = "swUpdateStrategy";
private TenantId tenantId;
/**
* "clientLwM2mSettings": {
* "fwUpdateStrategy": "1",
* "swUpdateStrategy": "1",
* "clientStrategy": "1"
* }
**/
private JsonObject postClientLwM2mSettings;
/**
* {"keyName": {
* "/3_1.0/0/1": "modelNumber",
* "/3_1.0/0/0": "manufacturer",
* "/3_1.0/0/2": "serialNumber"
* }
**/
private JsonObject postKeyNameProfile;
/**
* [ "/3_1.0/0/0", "/3_1.0/0/1"]
*/
private JsonArray postAttributeProfile;
/**
* [ "/3_1.0/0/0", "/3_1.0/0/2"]
*/
private JsonArray postTelemetryProfile;
/**
* [ "/3_1.0/0", "/3_1.0/0/1, "/3_1.0/0/2"]
*/
private JsonArray postObserveProfile;
/**
* "attributeLwm2m": {"/3_1.0": {"ver": "currentTimeTest11"},
* "/3_1.0/0": {"gt": 17},
* "/3_1.0/0/9": {"pmax": 45}, "/3_1.2": {ver": "3_1.2"}}
*/
private JsonObject postAttributeLwm2mProfile;
public LwM2mClientProfile clone() {
LwM2mClientProfile lwM2mClientProfile = new LwM2mClientProfile();
lwM2mClientProfile.postClientLwM2mSettings = this.deepCopy(this.postClientLwM2mSettings, JsonObject.class);
lwM2mClientProfile.postKeyNameProfile = this.deepCopy(this.postKeyNameProfile, JsonObject.class);
lwM2mClientProfile.postAttributeProfile = this.deepCopy(this.postAttributeProfile, JsonArray.class);
lwM2mClientProfile.postTelemetryProfile = this.deepCopy(this.postTelemetryProfile, JsonArray.class);
lwM2mClientProfile.postObserveProfile = this.deepCopy(this.postObserveProfile, JsonArray.class);
lwM2mClientProfile.postAttributeLwm2mProfile = this.deepCopy(this.postAttributeLwm2mProfile, JsonObject.class);
return lwM2mClientProfile;
}
private <T> T deepCopy(T elements, Class<T> type) {
try {
Gson gson = new Gson();
return gson.fromJson(gson.toJson(elements), type);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public int getClientStrategy() {
return this.postClientLwM2mSettings.getAsJsonObject().has(this.clientStrategyStr) ?
Integer.parseInt(this.postClientLwM2mSettings.getAsJsonObject().get(this.clientStrategyStr).getAsString()) :
LwM2MClientStrategy.CLIENT_STRATEGY_1.code;
}
public int getFwUpdateStrategy() {
return this.postClientLwM2mSettings.getAsJsonObject().has(this.fwUpdateStrategyStr) ?
Integer.parseInt(this.postClientLwM2mSettings.getAsJsonObject().get(this.fwUpdateStrategyStr).getAsString()) :
LwM2MFirmwareUpdateStrategy.OBJ_5_BINARY.code;
}
public int getSwUpdateStrategy() {
return this.postClientLwM2mSettings.getAsJsonObject().has(this.swUpdateStrategyStr) ?
Integer.parseInt(this.postClientLwM2mSettings.getAsJsonObject().get(this.swUpdateStrategyStr).getAsString()) :
LwM2MSoftwareUpdateStrategy.BINARY.code;
}
}

10
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientRpcRequest.java

@ -52,7 +52,7 @@ import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.S
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.START_JSON_KEY;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.TARGET_ID_VER_KEY;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.VALUE_KEY;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertPathFromIdVerToObjectId;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.fromVersionedIdToObjectId;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.validPathIdVer;
@Slf4j
@ -152,8 +152,8 @@ public class LwM2mClientRpcRequest {
else if (this.getTargetIdVer() != null
&& (EXECUTE == this.getTypeOper()
|| WRITE_REPLACE == this.getTypeOper())
&& !(new LwM2mPath(Objects.requireNonNull(convertPathFromIdVerToObjectId(this.getTargetIdVer()))).isResource()
|| new LwM2mPath(Objects.requireNonNull(convertPathFromIdVerToObjectId(this.getTargetIdVer()))).isResourceInstance())) {
&& !(new LwM2mPath(Objects.requireNonNull(fromVersionedIdToObjectId(this.getTargetIdVer()))).isResource()
|| new LwM2mPath(Objects.requireNonNull(fromVersionedIdToObjectId(this.getTargetIdVer()))).isResourceInstance())) {
this.setErrorMsg("Invalid parameter " + TARGET_ID_VER_KEY
+ ". Only Resource or ResourceInstance can be this operation");
}
@ -247,7 +247,7 @@ public class LwM2mClientRpcRequest {
private ConcurrentHashMap<String, Object> convertParamsToResourceId(ConcurrentHashMap<String, Object> params,
DefaultLwM2MUplinkMsgHandler serviceImpl) {
Map<String, Object> paramsIdVer = new ConcurrentHashMap<>();
LwM2mPath targetId = new LwM2mPath(Objects.requireNonNull(convertPathFromIdVerToObjectId(this.targetIdVer)));
LwM2mPath targetId = new LwM2mPath(Objects.requireNonNull(fromVersionedIdToObjectId(this.targetIdVer)));
if (targetId.isObjectInstance()) {
params.forEach((k, v) -> {
try {
@ -256,7 +256,7 @@ public class LwM2mClientRpcRequest {
} catch (NumberFormatException e) {
String targetIdVer = serviceImpl.getPresentPathIntoProfile(sessionInfo, k);
if (targetIdVer != null) {
LwM2mPath lwM2mPath = new LwM2mPath(Objects.requireNonNull(convertPathFromIdVerToObjectId(targetIdVer)));
LwM2mPath lwM2mPath = new LwM2mPath(Objects.requireNonNull(fromVersionedIdToObjectId(targetIdVer)));
paramsIdVer.put(String.valueOf(lwM2mPath.getResourceId()), v);
}
/** WRITE_UPDATE*/

4
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/ResultsAnalyzerParameters.java → common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/ParametersAnalyzeResult.java

@ -21,11 +21,11 @@ import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
@Data
public class ResultsAnalyzerParameters {
public class ParametersAnalyzeResult {
Set<String> pathPostParametersAdd;
Set<String> pathPostParametersDel;
public ResultsAnalyzerParameters() {
public ParametersAnalyzeResult() {
this.pathPostParametersAdd = ConcurrentHashMap.newKeySet();
this.pathPostParametersDel = ConcurrentHashMap.newKeySet();
}
Loading…
Cancel
Save