Browse Source

LWM2M: add requestUUID

pull/4607/head
nickAS21 5 years ago
parent
commit
4f2e72071d
  1. 202
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2MTransportMsgHandler.java
  2. 6
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mServerListener.java
  3. 144
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportRequest.java
  4. 110
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportUtil.java
  5. 43
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClient.java
  6. 2
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientContext.java
  7. 10
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientContextImpl.java
  8. 2
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mFwSwUpdate.java
  9. 273
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/Lwm2mClientRpcRequest.java

202
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2MTransportMsgHandler.java

@ -23,6 +23,7 @@ import com.google.gson.JsonElement;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.leshan.core.model.ObjectModel; import org.eclipse.leshan.core.model.ObjectModel;
import org.eclipse.leshan.core.model.ResourceModel; import org.eclipse.leshan.core.model.ResourceModel;
import org.eclipse.leshan.core.node.LwM2mObject; import org.eclipse.leshan.core.node.LwM2mObject;
@ -61,6 +62,7 @@ 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.LwM2mClientContext;
import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientProfile; 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.Lwm2mClientRpcRequest;
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.ResultsAddKeyValueProto;
import org.thingsboard.server.transport.lwm2m.server.client.ResultsAnalyzerParameters; import org.thingsboard.server.transport.lwm2m.server.client.ResultsAnalyzerParameters;
import org.thingsboard.server.transport.lwm2m.server.store.TbLwM2MDtlsSessionStore; import org.thingsboard.server.transport.lwm2m.server.store.TbLwM2MDtlsSessionStore;
@ -99,21 +101,20 @@ import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.L
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_VALUE; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_VALUE;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LWM2M_STRATEGY_2; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LWM2M_STRATEGY_2;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.DISCOVER; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.DISCOVER;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.DISCOVER_All;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.EXECUTE; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.EXECUTE;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.OBSERVE; 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;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.OBSERVE_READ_ALL; 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.READ;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.WRITE_ATTRIBUTES; 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.LwM2mTypeOper.WRITE_REPLACE;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.WRITE_UPDATE;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SW_ID; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SW_ID;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SW_RESULT_ID; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SW_RESULT_ID;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertJsonArrayToSet; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertJsonArrayToSet;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertPathFromIdVerToObjectId; 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.convertPathFromObjectIdToIdVer;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.getAckCallback; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.getAckCallback;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.setValidTypeOper;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.validateObjectVerFromKey; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.validateObjectVerFromKey;
@ -125,7 +126,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
private ExecutorService registrationExecutor; private ExecutorService registrationExecutor;
private ExecutorService updateRegistrationExecutor; private ExecutorService updateRegistrationExecutor;
private ExecutorService unRegistrationExecutor; private ExecutorService unRegistrationExecutor;
private LwM2mValueConverterImpl converter; public LwM2mValueConverterImpl converter;
private final TransportService transportService; private final TransportService transportService;
private final LwM2mTransportContext context; private final LwM2mTransportContext context;
@ -133,10 +134,10 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
public final FirmwareDataCache firmwareDataCache; public final FirmwareDataCache firmwareDataCache;
public final LwM2mTransportServerHelper helper; public final LwM2mTransportServerHelper helper;
private final LwM2MJsonAdaptor adaptor; private final LwM2MJsonAdaptor adaptor;
private final LwM2mClientContext clientContext;
private final LwM2mTransportRequest lwM2mTransportRequest;
private final TbLwM2MDtlsSessionStore sessionStore; private final TbLwM2MDtlsSessionStore sessionStore;
public final LwM2mClientContext clientContext;
public final LwM2mTransportRequest lwM2mTransportRequest;
private final Map<UUID, Long> rpcSubscriptions;
public DefaultLwM2MTransportMsgHandler(TransportService transportService, LwM2MTransportServerConfig config, LwM2mTransportServerHelper helper, public DefaultLwM2MTransportMsgHandler(TransportService transportService, LwM2MTransportServerConfig config, LwM2mTransportServerHelper helper,
LwM2mClientContext clientContext, LwM2mClientContext clientContext,
@ -151,6 +152,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
this.firmwareDataCache = firmwareDataCache; this.firmwareDataCache = firmwareDataCache;
this.context = context; this.context = context;
this.adaptor = adaptor; this.adaptor = adaptor;
this.rpcSubscriptions = new ConcurrentHashMap<>();
this.sessionStore = sessionStore; this.sessionStore = sessionStore;
} }
@ -241,16 +243,14 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
/** /**
* @param registration - Registration LwM2M Client * @param registration - Registration LwM2M Client
* @param observations - All paths observations before unReg * @param observations - !!! Warn: if have not finishing unReg, then this operation will be finished on next Client`s connect
* !!! Warn: if have not finishing unReg, then this operation will be finished on next Client`s connect
*/ */
public void unReg(Registration registration, Collection<Observation> observations) { public void unReg(Registration registration, Collection<Observation> observations) {
log.error("Client unRegistration -> test", new RuntimeException());
unRegistrationExecutor.submit(() -> { unRegistrationExecutor.submit(() -> {
try { try {
this.setCancelObservationsAll(registration);
this.sendLogsToThingsboard(LOG_LW2M_INFO + ": Client unRegistration", registration.getId()); this.sendLogsToThingsboard(LOG_LW2M_INFO + ": Client unRegistration", registration.getId());
this.closeClientSession(registration); this.closeClientSession(registration);
;
} catch (Throwable t) { } catch (Throwable t) {
log.error("[{}] endpoint [{}] error Unable un registration.", registration.getEndpoint(), t); log.error("[{}] endpoint [{}] error Unable un registration.", registration.getEndpoint(), t);
this.sendLogsToThingsboard(LOG_LW2M_ERROR + String.format(": Client Unable un Registration, %s", t.getMessage()), registration.getId()); this.sendLogsToThingsboard(LOG_LW2M_ERROR + String.format(": Client Unable un Registration, %s", t.getMessage()), registration.getId());
@ -285,12 +285,8 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
@Override @Override
public void setCancelObservationsAll(Registration registration) { public void setCancelObservationsAll(Registration registration) {
if (registration != null) { if (registration != null) {
lwM2mTransportRequest.sendAllRequest(registration, null, OBSERVE_CANCEL, lwM2mTransportRequest.sendAllRequest(registration, null, OBSERVE_CANCEL_ALL,
null, null, this.config.getTimeout(), null); null, null, this.config.getTimeout(), null);
// Set<Observation> observations = context.getServer().getObservationService().getObservations(registration);
// observations.forEach(observation -> lwM2mTransportRequest.sendAllRequest(registration,
// convertPathFromObjectIdToIdVer(observation.getPath().toString(), registration), OBSERVE_CANCEL,
// null, null, this.config.getTimeout(), null));
} }
} }
@ -354,12 +350,13 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
*/ */
@Override @Override
public void onAttributeUpdate(AttributeUpdateNotificationMsg msg, TransportProtos.SessionInfoProto sessionInfo) { public void onAttributeUpdate(AttributeUpdateNotificationMsg msg, TransportProtos.SessionInfoProto sessionInfo) {
LwM2mClient lwM2MClient = clientContext.getClient(new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB())); LwM2mClient lwM2MClient = clientContext.getClient(sessionInfo);
if (msg.getSharedUpdatedCount() > 0) { if (msg.getSharedUpdatedCount() > 0) {
msg.getSharedUpdatedList().forEach(tsKvProto -> { msg.getSharedUpdatedList().forEach(tsKvProto -> {
String pathName = tsKvProto.getKv().getKey(); String pathName = tsKvProto.getKv().getKey();
String pathIdVer = this.getPresentPathIntoProfile(sessionInfo, pathName); String pathIdVer = this.getPresentPathIntoProfile(sessionInfo, pathName);
Object valueNew = getValueFromKvProto(tsKvProto.getKv()); Object valueNew = getValueFromKvProto(tsKvProto.getKv());
log.warn("12) Shared AttributeUpdate start pathName [{}], pathIdVer [{}], valueNew [{}]", pathName, pathIdVer, valueNew);
if ((FirmwareUtil.getAttributeKey(FirmwareType.FIRMWARE, FirmwareKey.VERSION).equals(pathName) if ((FirmwareUtil.getAttributeKey(FirmwareType.FIRMWARE, FirmwareKey.VERSION).equals(pathName)
&& (!valueNew.equals(lwM2MClient.getFwUpdate().getCurrentVersion()))) && (!valueNew.equals(lwM2MClient.getFwUpdate().getCurrentVersion())))
|| (FirmwareUtil.getAttributeKey(FirmwareType.FIRMWARE, FirmwareKey.TITLE).equals(pathName) || (FirmwareUtil.getAttributeKey(FirmwareType.FIRMWARE, FirmwareKey.TITLE).equals(pathName)
@ -438,121 +435,49 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
clientContext.getLwM2mClients().forEach(e -> e.deleteResources(pathIdVer, this.config.getModelProvider())); clientContext.getLwM2mClients().forEach(e -> e.deleteResources(pathIdVer, this.config.getModelProvider()));
} }
/**
* #1 del from rpcSubscriptions by timeout
* #2 if not present in rpcSubscriptions by requestId: create new Lwm2mClientRpcRequest, after success - add requestId, timeout
*/
@Override @Override
public void onToDeviceRpcRequest(TransportProtos.ToDeviceRpcRequestMsg toDeviceRpcRequestMsg, SessionInfoProto sessionInfo) { public void onToDeviceRpcRequest(TransportProtos.ToDeviceRpcRequestMsg toDeviceRpcRequestMsg, SessionInfoProto sessionInfo) {
log.warn("4) RPC-OK finish to [{}]", toDeviceRpcRequestMsg); // #1
Lwm2mClientRpcRequest lwm2mClientRpcRequest = null; this.checkRpcRequestTimeout();
try { String bodyParams = StringUtils.trimToNull(toDeviceRpcRequestMsg.getParams()) != null ? toDeviceRpcRequestMsg.getParams() : "null";
Registration registration = clientContext.getClient(new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB())).getRegistration(); LwM2mTypeOper lwM2mTypeOper = setValidTypeOper(toDeviceRpcRequestMsg.getMethodName());
lwm2mClientRpcRequest = this.getDeviceRpcRequest(toDeviceRpcRequestMsg, sessionInfo, registration); UUID requestUUID = new UUID(toDeviceRpcRequestMsg.getRequestIdMSB(), toDeviceRpcRequestMsg.getRequestIdLSB());
if (lwm2mClientRpcRequest.getErrorMsg() != null) { log.warn("4) RPC-OK finish to [{}], keys: [{}]", requestUUID, this.rpcSubscriptions.keySet());
lwm2mClientRpcRequest.setResponseCode(BAD_REQUEST.name()); if (!this.rpcSubscriptions.containsKey(requestUUID)) {
this.onToDeviceRpcResponse(lwm2mClientRpcRequest.getDeviceRpcResponseResultMsg(), sessionInfo); this.rpcSubscriptions.put(requestUUID, toDeviceRpcRequestMsg.getExpirationTime());
} else { Lwm2mClientRpcRequest lwm2mClientRpcRequest = null;
lwM2mTransportRequest.sendAllRequest(registration, lwm2mClientRpcRequest.getTargetIdVer(), lwm2mClientRpcRequest.getTypeOper(), lwm2mClientRpcRequest.getContentFormatName(), try {
lwm2mClientRpcRequest.getValue() == null ? lwm2mClientRpcRequest.getParams() : lwm2mClientRpcRequest.getValue(), Registration registration = clientContext.getClient(sessionInfo).getRegistration();
this.config.getTimeout(), lwm2mClientRpcRequest); lwm2mClientRpcRequest = new Lwm2mClientRpcRequest(lwM2mTypeOper, bodyParams, toDeviceRpcRequestMsg.getRequestId(), sessionInfo, registration, this);
} if (lwm2mClientRpcRequest.getErrorMsg() != null) {
} catch (Exception e) { lwm2mClientRpcRequest.setResponseCode(BAD_REQUEST.name());
if (lwm2mClientRpcRequest == null) { this.onToDeviceRpcResponse(lwm2mClientRpcRequest.getDeviceRpcResponseResultMsg(), sessionInfo);
lwm2mClientRpcRequest = new Lwm2mClientRpcRequest(); } else {
} lwM2mTransportRequest.sendAllRequest(registration, lwm2mClientRpcRequest.getTargetIdVer(), lwm2mClientRpcRequest.getTypeOper(),
lwm2mClientRpcRequest.setResponseCode(BAD_REQUEST.name()); null,
if (lwm2mClientRpcRequest.getErrorMsg() == null) { lwm2mClientRpcRequest.getValue() == null ? lwm2mClientRpcRequest.getParams() : lwm2mClientRpcRequest.getValue(),
lwm2mClientRpcRequest.setErrorMsg(e.getMessage()); this.config.getTimeout(), lwm2mClientRpcRequest);
}
this.onToDeviceRpcResponse(lwm2mClientRpcRequest.getDeviceRpcResponseResultMsg(), sessionInfo);
}
}
private Lwm2mClientRpcRequest getDeviceRpcRequest(TransportProtos.ToDeviceRpcRequestMsg toDeviceRequest,
SessionInfoProto sessionInfo, Registration registration) throws IllegalArgumentException {
Lwm2mClientRpcRequest lwm2mClientRpcRequest = new Lwm2mClientRpcRequest();
try {
lwm2mClientRpcRequest.setRequestId(toDeviceRequest.getRequestId());
lwm2mClientRpcRequest.setSessionInfo(sessionInfo);
lwm2mClientRpcRequest.setValidTypeOper(toDeviceRequest.getMethodName());
JsonObject rpcRequest = LwM2mTransportUtil.validateJson(toDeviceRequest.getParams());
if (rpcRequest != null) {
if (rpcRequest.has(lwm2mClientRpcRequest.keyNameKey)) {
String targetIdVer = this.getPresentPathIntoProfile(sessionInfo,
rpcRequest.get(lwm2mClientRpcRequest.keyNameKey).getAsString());
if (targetIdVer != null) {
lwm2mClientRpcRequest.setTargetIdVer(targetIdVer);
lwm2mClientRpcRequest.setInfoMsg(String.format("Changed by: key - %s, pathIdVer - %s",
rpcRequest.get(lwm2mClientRpcRequest.keyNameKey).getAsString(), targetIdVer));
}
}
if (lwm2mClientRpcRequest.getTargetIdVer() == null) {
lwm2mClientRpcRequest.setValidTargetIdVerKey(rpcRequest, registration);
}
if (rpcRequest.has(lwm2mClientRpcRequest.contentFormatNameKey)) {
lwm2mClientRpcRequest.setValidContentFormatName(rpcRequest);
}
if (rpcRequest.has(lwm2mClientRpcRequest.timeoutInMsKey) && rpcRequest.get(lwm2mClientRpcRequest.timeoutInMsKey).getAsLong() > 0) {
lwm2mClientRpcRequest.setTimeoutInMs(rpcRequest.get(lwm2mClientRpcRequest.timeoutInMsKey).getAsLong());
}
if (rpcRequest.has(lwm2mClientRpcRequest.valueKey)) {
lwm2mClientRpcRequest.setValue(rpcRequest.get(lwm2mClientRpcRequest.valueKey).getAsString());
}
if (rpcRequest.has(lwm2mClientRpcRequest.paramsKey) && rpcRequest.get(lwm2mClientRpcRequest.paramsKey).isJsonObject()) {
ConcurrentHashMap<String, Object> params = new Gson().fromJson(rpcRequest.get(lwm2mClientRpcRequest.paramsKey)
.getAsJsonObject().toString(), new TypeToken<ConcurrentHashMap<String, Object>>() {
}.getType());
if (WRITE_UPDATE == lwm2mClientRpcRequest.getTypeOper()) {
ConcurrentHashMap<String, Object> paramsResourceId = convertParamsToResourceId(params, sessionInfo);
if (paramsResourceId.size() > 0) {
lwm2mClientRpcRequest.setParams(paramsResourceId);
}
} else {
lwm2mClientRpcRequest.setParams(params);
}
} else if (rpcRequest.has(lwm2mClientRpcRequest.paramsKey) && rpcRequest.get(lwm2mClientRpcRequest.paramsKey).isJsonArray()) {
new Gson().fromJson(rpcRequest.get(lwm2mClientRpcRequest.paramsKey)
.getAsJsonObject().toString(), new TypeToken<ConcurrentHashMap<String, Object>>() {
}.getType());
} }
lwm2mClientRpcRequest.setSessionInfo(sessionInfo); } catch (Exception e) {
if (!(OBSERVE_READ_ALL == lwm2mClientRpcRequest.getTypeOper() if (lwm2mClientRpcRequest == null) {
|| DISCOVER_All == lwm2mClientRpcRequest.getTypeOper() lwm2mClientRpcRequest = new Lwm2mClientRpcRequest();
|| OBSERVE_CANCEL == lwm2mClientRpcRequest.getTypeOper())
&& lwm2mClientRpcRequest.getTargetIdVer() == null) {
lwm2mClientRpcRequest.setErrorMsg(lwm2mClientRpcRequest.targetIdVerKey + " and " +
lwm2mClientRpcRequest.keyNameKey + " is null or bad format");
} }
/** lwm2mClientRpcRequest.setResponseCode(BAD_REQUEST.name());
* EXECUTE && WRITE_REPLACE - only for Resource or ResourceInstance if (lwm2mClientRpcRequest.getErrorMsg() == null) {
*/ lwm2mClientRpcRequest.setErrorMsg(e.getMessage());
else if ((EXECUTE == lwm2mClientRpcRequest.getTypeOper()
|| WRITE_REPLACE == lwm2mClientRpcRequest.getTypeOper())
&& lwm2mClientRpcRequest.getTargetIdVer() != null
&& !(new LwM2mPath(convertPathFromIdVerToObjectId(lwm2mClientRpcRequest.getTargetIdVer())).isResource()
|| new LwM2mPath(convertPathFromIdVerToObjectId(lwm2mClientRpcRequest.getTargetIdVer())).isResourceInstance())) {
lwm2mClientRpcRequest.setErrorMsg("Invalid parameter " + lwm2mClientRpcRequest.targetIdVerKey
+ ". Only Resource or ResourceInstance can be this operation");
} }
} else { this.onToDeviceRpcResponse(lwm2mClientRpcRequest.getDeviceRpcResponseResultMsg(), sessionInfo);
lwm2mClientRpcRequest.setErrorMsg("Params of request is bad Json format.");
} }
} catch (Exception e) {
throw new IllegalArgumentException(lwm2mClientRpcRequest.getErrorMsg());
} }
return lwm2mClientRpcRequest;
} }
private ConcurrentHashMap<String, Object> convertParamsToResourceId(ConcurrentHashMap<String, Object> params, private void checkRpcRequestTimeout() {
SessionInfoProto sessionInfo) { Set<UUID> rpcSubscriptionsToRemove = rpcSubscriptions.entrySet().stream().filter(kv -> System.currentTimeMillis() > kv.getValue()).map(Map.Entry::getKey).collect(Collectors.toSet());
ConcurrentHashMap<String, Object> paramsIdVer = new ConcurrentHashMap<>(); rpcSubscriptionsToRemove.forEach(rpcSubscriptions::remove);
params.forEach((k, v) -> {
String targetIdVer = this.getPresentPathIntoProfile(sessionInfo, k);
if (targetIdVer != null) {
LwM2mPath targetId = new LwM2mPath(convertPathFromIdVerToObjectId(targetIdVer));
if (targetId.isResource()) {
paramsIdVer.put(String.valueOf(targetId.getResourceId()), v);
}
}
});
return paramsIdVer;
} }
public void sentRpcRequest(Lwm2mClientRpcRequest rpcRequest, String requestCode, String msg, String typeMsg) { public void sentRpcRequest(Lwm2mClientRpcRequest rpcRequest, String requestCode, String msg, String typeMsg) {
@ -722,10 +647,10 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
* set setClient_fw_info... = value * set setClient_fw_info... = value
**/ **/
if (lwM2MClient.getFwUpdate().isInfoFwSwUpdate()) { if (lwM2MClient.getFwUpdate().isInfoFwSwUpdate()) {
lwM2MClient.getFwUpdate().initReadValue(this, lwM2mTransportRequest, path); lwM2MClient.getFwUpdate().initReadValue(this, this.lwM2mTransportRequest, path);
} }
if (lwM2MClient.getSwUpdate().isInfoFwSwUpdate()) { if (lwM2MClient.getSwUpdate().isInfoFwSwUpdate()) {
lwM2MClient.getSwUpdate().initReadValue(this, lwM2mTransportRequest, path); lwM2MClient.getSwUpdate().initReadValue(this, this.lwM2mTransportRequest, path);
} }
/** /**
@ -742,7 +667,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
&& (convertPathFromObjectIdToIdVer(FW_RESULT_ID, registration).equals(path))) { && (convertPathFromObjectIdToIdVer(FW_RESULT_ID, registration).equals(path))) {
if (DOWNLOADED.name().equals(lwM2MClient.getFwUpdate().getStateUpdate()) if (DOWNLOADED.name().equals(lwM2MClient.getFwUpdate().getStateUpdate())
&& lwM2MClient.getFwUpdate().conditionalFwExecuteStart()) { && lwM2MClient.getFwUpdate().conditionalFwExecuteStart()) {
lwM2MClient.getFwUpdate().executeFwSwWare(this, lwM2mTransportRequest); lwM2MClient.getFwUpdate().executeFwSwWare(this, this.lwM2mTransportRequest);
} else if (UPDATING.name().equals(lwM2MClient.getFwUpdate().getStateUpdate()) } else if (UPDATING.name().equals(lwM2MClient.getFwUpdate().getStateUpdate())
&& lwM2MClient.getFwUpdate().conditionalFwExecuteAfterSuccess()) { && lwM2MClient.getFwUpdate().conditionalFwExecuteAfterSuccess()) {
lwM2MClient.getFwUpdate().finishFwSwUpdate(this, true); lwM2MClient.getFwUpdate().finishFwSwUpdate(this, true);
@ -767,7 +692,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
&& (convertPathFromObjectIdToIdVer(SW_RESULT_ID, registration).equals(path))) { && (convertPathFromObjectIdToIdVer(SW_RESULT_ID, registration).equals(path))) {
if (DOWNLOADED.name().equals(lwM2MClient.getSwUpdate().getStateUpdate()) if (DOWNLOADED.name().equals(lwM2MClient.getSwUpdate().getStateUpdate())
&& lwM2MClient.getSwUpdate().conditionalSwUpdateExecute()) { && lwM2MClient.getSwUpdate().conditionalSwUpdateExecute()) {
lwM2MClient.getSwUpdate().executeFwSwWare(this, lwM2mTransportRequest); lwM2MClient.getSwUpdate().executeFwSwWare(this, this.lwM2mTransportRequest);
} else if (UPDATING.name().equals(lwM2MClient.getSwUpdate().getStateUpdate()) } else if (UPDATING.name().equals(lwM2MClient.getSwUpdate().getStateUpdate())
&& lwM2MClient.getSwUpdate().conditionalSwExecuteAfterSuccess()) { && lwM2MClient.getSwUpdate().conditionalSwExecuteAfterSuccess()) {
lwM2MClient.getSwUpdate().finishFwSwUpdate(this, true); lwM2MClient.getSwUpdate().finishFwSwUpdate(this, true);
@ -970,11 +895,14 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
* @return - return value of Resource by idPath * @return - return value of Resource by idPath
*/ */
private LwM2mResource getResourceValueFromLwM2MClient(LwM2mClient lwM2MClient, String path) { private LwM2mResource getResourceValueFromLwM2MClient(LwM2mClient lwM2MClient, String path) {
LwM2mResource resourceValue = null; LwM2mResource lwm2mResourceValue = null;
if (new LwM2mPath(convertPathFromIdVerToObjectId(path)).isResource()) { ResourceValue resourceValue = lwM2MClient.getResources().get(path);
resourceValue = lwM2MClient.getResources().get(path).getLwM2mResource(); if (resourceValue != null) {
if (new LwM2mPath(convertPathFromIdVerToObjectId(path)).isResource()) {
lwm2mResourceValue = lwM2MClient.getResources().get(path).getLwM2mResource();
}
} }
return resourceValue; return lwm2mResourceValue;
} }
/** /**
@ -1281,7 +1209,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
* @param name - * @param name -
* @return - * @return -
*/ */
private String getPresentPathIntoProfile(TransportProtos.SessionInfoProto sessionInfo, String name) { public String getPresentPathIntoProfile(TransportProtos.SessionInfoProto sessionInfo, String name) {
LwM2mClientProfile profile = clientContext.getProfile(new UUID(sessionInfo.getDeviceProfileIdMSB(), sessionInfo.getDeviceProfileIdLSB())); LwM2mClientProfile profile = clientContext.getProfile(new UUID(sessionInfo.getDeviceProfileIdMSB(), sessionInfo.getDeviceProfileIdLSB()));
LwM2mClient lwM2mClient = clientContext.getClient(sessionInfo); LwM2mClient lwM2mClient = clientContext.getClient(sessionInfo);
return profile.getPostKeyNameProfile().getAsJsonObject().entrySet().stream() return profile.getPostKeyNameProfile().getAsJsonObject().entrySet().stream()
@ -1304,7 +1232,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
this.updateAttributeFromThingsboard(tsKvProtos, sessionInfo); this.updateAttributeFromThingsboard(tsKvProtos, sessionInfo);
} catch (Exception e) { } catch (Exception e) {
log.error(String.valueOf(e)); log.error("", e);
} }
} }
@ -1378,6 +1306,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
private void reportActivityAndRegister(SessionInfoProto sessionInfo) { private void reportActivityAndRegister(SessionInfoProto sessionInfo) {
if (sessionInfo != null && transportService.reportActivity(sessionInfo) == null) { if (sessionInfo != null && transportService.reportActivity(sessionInfo) == null) {
transportService.registerAsyncSession(sessionInfo, new LwM2mSessionMsgListener(this, sessionInfo)); transportService.registerAsyncSession(sessionInfo, new LwM2mSessionMsgListener(this, sessionInfo));
this.reportActivitySubscription(sessionInfo);
} }
} }
@ -1510,4 +1439,11 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
return this.config; return this.config;
} }
private void reportActivitySubscription(TransportProtos.SessionInfoProto sessionInfo) {
transportService.process(sessionInfo, TransportProtos.SubscriptionInfoProto.newBuilder()
.setAttributeSubscription(true)
.setRpcSubscription(true)
.setLastActivityTime(System.currentTimeMillis())
.build(), TransportServiceCallback.EMPTY);
}
} }

6
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mServerListener.java

@ -94,12 +94,6 @@ public class LwM2mServerListener {
@Override @Override
public void onResponse(Observation observation, Registration registration, ObserveResponse response) { public void onResponse(Observation observation, Registration registration, ObserveResponse response) {
if (registration != null) { if (registration != null) {
// if (observation.getPath().isResource() || observation.getPath().isResourceInstance()) {
// String msg = String.format("%s: Successful Observation %s.", LOG_LW2M_INFO,
// observation.getPath());
// log.warn(msg);
// service.sendLogsToThingsboard(msg, registration.getId());
// }
service.onUpdateValueAfterReadResponse(registration, convertPathFromObjectIdToIdVer(observation.getPath().toString(), service.onUpdateValueAfterReadResponse(registration, convertPathFromObjectIdToIdVer(observation.getPath().toString(),
registration), response, null); registration), response, null);
} }

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

@ -22,6 +22,8 @@ import org.eclipse.californium.core.coap.Response;
import org.eclipse.leshan.core.Link; import org.eclipse.leshan.core.Link;
import org.eclipse.leshan.core.model.ResourceModel; import org.eclipse.leshan.core.model.ResourceModel;
import org.eclipse.leshan.core.node.LwM2mNode; import org.eclipse.leshan.core.node.LwM2mNode;
import org.eclipse.leshan.core.node.LwM2mObject;
import org.eclipse.leshan.core.node.LwM2mObjectInstance;
import org.eclipse.leshan.core.node.LwM2mPath; import org.eclipse.leshan.core.node.LwM2mPath;
import org.eclipse.leshan.core.node.LwM2mResource; import org.eclipse.leshan.core.node.LwM2mResource;
import org.eclipse.leshan.core.node.LwM2mSingleResource; import org.eclipse.leshan.core.node.LwM2mSingleResource;
@ -34,6 +36,7 @@ import org.eclipse.leshan.core.request.DownlinkRequest;
import org.eclipse.leshan.core.request.ExecuteRequest; import org.eclipse.leshan.core.request.ExecuteRequest;
import org.eclipse.leshan.core.request.ObserveRequest; import org.eclipse.leshan.core.request.ObserveRequest;
import org.eclipse.leshan.core.request.ReadRequest; import org.eclipse.leshan.core.request.ReadRequest;
import org.eclipse.leshan.core.request.WriteAttributesRequest;
import org.eclipse.leshan.core.request.WriteRequest; import org.eclipse.leshan.core.request.WriteRequest;
import org.eclipse.leshan.core.request.exception.ClientSleepingException; import org.eclipse.leshan.core.request.exception.ClientSleepingException;
import org.eclipse.leshan.core.response.DeleteResponse; import org.eclipse.leshan.core.response.DeleteResponse;
@ -79,10 +82,12 @@ import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.L
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_VALUE; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_VALUE;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.DISCOVER; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.DISCOVER;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.DISCOVER_All; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.DISCOVER_ALL;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.EXECUTE; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.EXECUTE;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.OBSERVE_CANCEL; 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.OBSERVE_READ_ALL; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.OBSERVE_READ_ALL;
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.LwM2mTypeOper.WRITE_REPLACE;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.WRITE_UPDATE; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.WRITE_UPDATE;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.RESPONSE_REQUEST_CHANNEL; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.RESPONSE_REQUEST_CHANNEL;
@ -123,7 +128,7 @@ public class LwM2mTransportRequest {
*/ */
public void sendAllRequest(Registration registration, String targetIdVer, LwM2mTypeOper typeOper, public void sendAllRequest(Registration registration, String targetIdVer, LwM2mTypeOper typeOper,
String contentFormatName, Object params, long timeoutInMs, Lwm2mClientRpcRequest rpcRequest) { String contentFormatName, Object params, long timeoutInMs, Lwm2mClientRpcRequest lwm2mClientRpcRequest) {
try { try {
String target = convertPathFromIdVerToObjectId(targetIdVer); String target = convertPathFromIdVerToObjectId(targetIdVer);
ContentFormat contentFormat = contentFormatName != null ? ContentFormat.fromName(contentFormatName.toUpperCase()) : ContentFormat.DEFAULT; ContentFormat contentFormat = contentFormatName != null ? ContentFormat.fromName(contentFormatName.toUpperCase()) : ContentFormat.DEFAULT;
@ -132,45 +137,42 @@ public class LwM2mTransportRequest {
if (!OBSERVE_READ_ALL.name().equals(typeOper.name()) && resultIds != null && registration != null && resultIds.getObjectId() >= 0 && lwM2MClient != null) { if (!OBSERVE_READ_ALL.name().equals(typeOper.name()) && resultIds != null && registration != null && resultIds.getObjectId() >= 0 && lwM2MClient != null) {
if (lwM2MClient.isValidObjectVersion(targetIdVer)) { if (lwM2MClient.isValidObjectVersion(targetIdVer)) {
timeoutInMs = timeoutInMs > 0 ? timeoutInMs : DEFAULT_TIMEOUT; timeoutInMs = timeoutInMs > 0 ? timeoutInMs : DEFAULT_TIMEOUT;
DownlinkRequest request = createRequest (registration, lwM2MClient, typeOper, contentFormat, target, DownlinkRequest request = createRequest(registration, lwM2MClient, typeOper, contentFormat, target,
targetIdVer, resultIds, params, rpcRequest); targetIdVer, resultIds, params, lwm2mClientRpcRequest);
if (request != null) { if (request != null) {
try { try {
this.sendRequest(registration, lwM2MClient, request, timeoutInMs, rpcRequest); this.sendRequest(registration, lwM2MClient, request, timeoutInMs, lwm2mClientRpcRequest);
} catch (ClientSleepingException e) { } catch (ClientSleepingException e) {
DownlinkRequest finalRequest = request; DownlinkRequest finalRequest = request;
long finalTimeoutInMs = timeoutInMs; long finalTimeoutInMs = timeoutInMs;
Lwm2mClientRpcRequest finalRpcRequest = rpcRequest; Lwm2mClientRpcRequest finalRpcRequest = lwm2mClientRpcRequest;
lwM2MClient.getQueuedRequests().add(() -> sendRequest(registration, lwM2MClient, finalRequest, finalTimeoutInMs, finalRpcRequest)); lwM2MClient.getQueuedRequests().add(() -> sendRequest(registration, lwM2MClient, finalRequest, finalTimeoutInMs, finalRpcRequest));
} catch (Exception e) { } catch (Exception e) {
log.error("[{}] [{}] [{}] Failed to send downlink.", registration.getEndpoint(), targetIdVer, typeOper.name(), e); log.error("[{}] [{}] [{}] Failed to send downlink.", registration.getEndpoint(), targetIdVer, typeOper.name(), e);
} }
} } else if (WRITE_UPDATE.name().equals(typeOper.name())) {
else if (WRITE_UPDATE.name().equals(typeOper.name())) { if (lwm2mClientRpcRequest != null) {
if (rpcRequest != null) {
String errorMsg = String.format("Path %s params is not valid", targetIdVer); String errorMsg = String.format("Path %s params is not valid", targetIdVer);
handler.sentRpcRequest(rpcRequest, BAD_REQUEST.getName(), errorMsg, LOG_LW2M_ERROR); handler.sentRpcRequest(lwm2mClientRpcRequest, BAD_REQUEST.getName(), errorMsg, LOG_LW2M_ERROR);
} }
} } else if (WRITE_REPLACE.name().equals(typeOper.name()) || EXECUTE.name().equals(typeOper.name())) {
else if (WRITE_REPLACE.name().equals(typeOper.name()) || EXECUTE.name().equals(typeOper.name()) ) { if (lwm2mClientRpcRequest != null) {
if (rpcRequest != null) {
String errorMsg = String.format("Path %s object model is absent", targetIdVer); String errorMsg = String.format("Path %s object model is absent", targetIdVer);
handler.sentRpcRequest(rpcRequest, BAD_REQUEST.getName(), errorMsg, LOG_LW2M_ERROR); handler.sentRpcRequest(lwm2mClientRpcRequest, BAD_REQUEST.getName(), errorMsg, LOG_LW2M_ERROR);
} }
} } else if (!OBSERVE_CANCEL.name().equals(typeOper.name())) {
else if (!OBSERVE_CANCEL.name().equals(typeOper.name())) {
log.error("[{}], [{}] - [{}] error SendRequest", registration.getEndpoint(), typeOper.name(), targetIdVer); log.error("[{}], [{}] - [{}] error SendRequest", registration.getEndpoint(), typeOper.name(), targetIdVer);
if (rpcRequest != null) { if (lwm2mClientRpcRequest != null) {
ResourceModel resourceModel = lwM2MClient.getResourceModel(targetIdVer, this.config.getModelProvider()); ResourceModel resourceModel = lwM2MClient.getResourceModel(targetIdVer, this.config.getModelProvider());
String errorMsg = resourceModel == null ? String.format("Path %s not found in object version", targetIdVer) : "SendRequest - null"; String errorMsg = resourceModel == null ? String.format("Path %s not found in object version", targetIdVer) : "SendRequest - null";
handler.sentRpcRequest(rpcRequest, NOT_FOUND.getName(), errorMsg, LOG_LW2M_ERROR); this.handler.sentRpcRequest(lwm2mClientRpcRequest, NOT_FOUND.getName(), errorMsg, LOG_LW2M_ERROR);
} }
} }
} else if (rpcRequest != null) { } else if (lwm2mClientRpcRequest != null) {
String errorMsg = String.format("Path %s not found in object version", targetIdVer); String errorMsg = String.format("Path %s not found in object version", targetIdVer);
handler.sentRpcRequest(rpcRequest, NOT_FOUND.getName(), errorMsg, LOG_LW2M_ERROR); this.handler.sentRpcRequest(lwm2mClientRpcRequest, NOT_FOUND.getName(), errorMsg, LOG_LW2M_ERROR);
} }
} else if (OBSERVE_READ_ALL.name().equals(typeOper.name()) || DISCOVER_All.name().equals(typeOper.name())) { } else if (OBSERVE_READ_ALL.name().equals(typeOper.name()) || DISCOVER_ALL.name().equals(typeOper.name())) {
Set<String> paths; Set<String> paths;
if (OBSERVE_READ_ALL.name().equals(typeOper.name())) { if (OBSERVE_READ_ALL.name().equals(typeOper.name())) {
Set<Observation> observations = context.getServer().getObservationService().getObservations(registration); Set<Observation> observations = context.getServer().getObservationService().getObservations(registration);
@ -179,34 +181,34 @@ public class LwM2mTransportRequest {
assert registration != null; assert registration != null;
Link[] objectLinks = registration.getSortedObjectLinks(); Link[] objectLinks = registration.getSortedObjectLinks();
paths = Arrays.stream(objectLinks).map(Link::toString).collect(Collectors.toUnmodifiableSet()); paths = Arrays.stream(objectLinks).map(Link::toString).collect(Collectors.toUnmodifiableSet());
String msg = String.format("%s: type operation %s paths - %s", LOG_LW2M_INFO,
typeOper.name(), paths);
handler.sendLogsToThingsboard(msg, registration.getId());
} }
if (rpcRequest != null) { String msg = String.format("%s: type operation %s paths - %s", LOG_LW2M_INFO,
typeOper.name(), paths);
this.handler.sendLogsToThingsboard(msg, registration.getId());
if (lwm2mClientRpcRequest != null) {
String valueMsg = String.format("Paths - %s", paths); String valueMsg = String.format("Paths - %s", paths);
handler.sentRpcRequest(rpcRequest, CONTENT.name(), valueMsg, LOG_LW2M_VALUE); this.handler.sentRpcRequest(lwm2mClientRpcRequest, CONTENT.name(), valueMsg, LOG_LW2M_VALUE);
} }
} else if (OBSERVE_CANCEL.name().equals(typeOper.name())) { } else if (OBSERVE_CANCEL_ALL.name().equals(typeOper.name())) {
int observeCancelCnt = context.getServer().getObservationService().cancelObservations(registration); int observeCancelCnt = context.getServer().getObservationService().cancelObservations(registration);
String observeCancelMsgAll = String.format("%s: type operation %s paths: All count: %d", LOG_LW2M_INFO, String observeCancelMsgAll = String.format("%s: type operation %s paths: All count: %d", LOG_LW2M_INFO,
OBSERVE_CANCEL.name(), observeCancelCnt); OBSERVE_CANCEL.name(), observeCancelCnt);
this.afterObserveCancel(registration, observeCancelCnt, observeCancelMsgAll, rpcRequest); this.afterObserveCancel(registration, observeCancelCnt, observeCancelMsgAll, lwm2mClientRpcRequest);
} }
} catch (Exception e) { } catch (Exception e) {
String msg = String.format("%s: type operation %s %s", LOG_LW2M_ERROR, String msg = String.format("%s: type operation %s %s", LOG_LW2M_ERROR,
typeOper.name(), e.getMessage()); typeOper.name(), e.getMessage());
handler.sendLogsToThingsboard(msg, registration.getId()); handler.sendLogsToThingsboard(msg, registration.getId());
if (rpcRequest != null) { if (lwm2mClientRpcRequest != null) {
String errorMsg = String.format("Path %s type operation %s %s", targetIdVer, typeOper.name(), e.getMessage()); String errorMsg = String.format("Path %s type operation %s %s", targetIdVer, typeOper.name(), e.getMessage());
handler.sentRpcRequest(rpcRequest, NOT_FOUND.getName(), errorMsg, LOG_LW2M_ERROR); handler.sentRpcRequest(lwm2mClientRpcRequest, NOT_FOUND.getName(), errorMsg, LOG_LW2M_ERROR);
} }
} }
} }
private DownlinkRequest createRequest (Registration registration, LwM2mClient lwM2MClient, LwM2mTypeOper typeOper, private DownlinkRequest createRequest(Registration registration, LwM2mClient lwM2MClient, LwM2mTypeOper typeOper,
ContentFormat contentFormat, String target, String targetIdVer, ContentFormat contentFormat, String target, String targetIdVer,
LwM2mPath resultIds, Object params, Lwm2mClientRpcRequest rpcRequest) { LwM2mPath resultIds, Object params, Lwm2mClientRpcRequest rpcRequest) {
DownlinkRequest request = null; DownlinkRequest request = null;
switch (typeOper) { switch (typeOper) {
case READ: case READ:
@ -216,7 +218,7 @@ public class LwM2mTransportRequest {
request = new DiscoverRequest(target); request = new DiscoverRequest(target);
break; break;
case OBSERVE: case OBSERVE:
String msg = String.format("%s: Send Observation %s.", LOG_LW2M_INFO, targetIdVer); String msg = String.format("%s: Send Observation %s.", LOG_LW2M_INFO, targetIdVer);
log.warn(msg); log.warn(msg);
if (resultIds.isResource()) { if (resultIds.isResource()) {
Set<Observation> observations = context.getServer().getObservationService().getObservations(registration); Set<Observation> observations = context.getServer().getObservationService().getObservations(registration);
@ -305,7 +307,7 @@ public class LwM2mTransportRequest {
} }
break; break;
case WRITE_ATTRIBUTES: case WRITE_ATTRIBUTES:
request = createWriteAttributeRequest(target, params); request = createWriteAttributeRequest(target, params, this.handler);
break; break;
case DELETE: case DELETE:
request = new DeleteRequest(target); request = new DeleteRequest(target);
@ -347,10 +349,10 @@ public class LwM2mTransportRequest {
set setClient_fw_info... = empty set setClient_fw_info... = empty
**/ **/
if (lwM2MClient.getFwUpdate().isInfoFwSwUpdate()) { if (lwM2MClient.getFwUpdate().isInfoFwSwUpdate()) {
lwM2MClient.getFwUpdate().initReadValue(handler, request.getPath().toString()); lwM2MClient.getFwUpdate().initReadValue(handler, this, request.getPath().toString());
} }
if (lwM2MClient.getSwUpdate().isInfoFwSwUpdate()) { if (lwM2MClient.getSwUpdate().isInfoFwSwUpdate()) {
lwM2MClient.getSwUpdate().initReadValue(handler, request.getPath().toString()); lwM2MClient.getSwUpdate().initReadValue(handler, this, request.getPath().toString());
} }
if (request.getPath().toString().equals(FW_PACKAGE_ID) || request.getPath().toString().equals(SW_PACKAGE_ID)) { if (request.getPath().toString().equals(FW_PACKAGE_ID) || request.getPath().toString().equals(SW_PACKAGE_ID)) {
this.afterWriteFwSWUpdateError(registration, request, response.getErrorMessage()); this.afterWriteFwSWUpdateError(registration, request, response.getErrorMessage());
@ -364,10 +366,10 @@ public class LwM2mTransportRequest {
set setClient_fw_info... = empty set setClient_fw_info... = empty
**/ **/
if (lwM2MClient.getFwUpdate().isInfoFwSwUpdate()) { if (lwM2MClient.getFwUpdate().isInfoFwSwUpdate()) {
lwM2MClient.getFwUpdate().initReadValue(handler, request.getPath().toString()); lwM2MClient.getFwUpdate().initReadValue(handler, this, request.getPath().toString());
} }
if (lwM2MClient.getSwUpdate().isInfoFwSwUpdate()) { if (lwM2MClient.getSwUpdate().isInfoFwSwUpdate()) {
lwM2MClient.getSwUpdate().initReadValue(handler, request.getPath().toString()); lwM2MClient.getSwUpdate().initReadValue(handler, this, request.getPath().toString());
} }
if (request.getPath().toString().equals(FW_PACKAGE_ID) || request.getPath().toString().equals(SW_PACKAGE_ID)) { if (request.getPath().toString().equals(FW_PACKAGE_ID) || request.getPath().toString().equals(SW_PACKAGE_ID)) {
this.afterWriteFwSWUpdateError(registration, request, e.getMessage()); this.afterWriteFwSWUpdateError(registration, request, e.getMessage());
@ -473,7 +475,13 @@ public class LwM2mTransportRequest {
} else if (response instanceof ExecuteResponse) { } else if (response instanceof ExecuteResponse) {
log.warn("[{}] Path [{}] ExecuteResponse 7_Send", pathIdVer, response); log.warn("[{}] Path [{}] ExecuteResponse 7_Send", pathIdVer, response);
} else if (response instanceof WriteAttributesResponse) { } else if (response instanceof WriteAttributesResponse) {
msgLog = String.format("%s: type operation: %s path: %s value: %s",
LOG_LW2M_INFO, WRITE_ATTRIBUTES.name(), request.getPath().toString(), ((WriteAttributesRequest) request).getAttributes().toString());
handler.sendLogsToThingsboard(msgLog, registration.getId());
log.warn("[{}] Path [{}] WriteAttributesResponse 8_Send", pathIdVer, response); log.warn("[{}] Path [{}] WriteAttributesResponse 8_Send", pathIdVer, response);
if (rpcRequest != null) {
handler.sentRpcRequest(rpcRequest, response.getCode().getName(), response.toString(), LOG_LW2M_VALUE);
}
} else if (response instanceof WriteResponse) { } else if (response instanceof WriteResponse) {
log.warn("[{}] Path [{}] WriteResponse 9_Send", pathIdVer, response); log.warn("[{}] Path [{}] WriteResponse 9_Send", pathIdVer, response);
this.infoWriteResponse(registration, response, request); this.infoWriteResponse(registration, response, request);
@ -494,29 +502,37 @@ public class LwM2mTransportRequest {
private void infoWriteResponse(Registration registration, LwM2mResponse response, DownlinkRequest request) { private void infoWriteResponse(Registration registration, LwM2mResponse response, DownlinkRequest request) {
try { try {
LwM2mNode node = ((WriteRequest) request).getNode(); LwM2mNode node = ((WriteRequest) request).getNode();
String msg; String msg = null;
Object value; Object value;
LwM2mSingleResource singleResource = (LwM2mSingleResource) node; if (node instanceof LwM2mObject) {
if (singleResource.getType() == ResourceModel.Type.STRING || singleResource.getType() == ResourceModel.Type.OPAQUE) { msg = String.format("%s: Update finished successfully: Lwm2m code - %d Source path: %s value: %s",
int valueLength; LOG_LW2M_INFO, response.getCode().getCode(), request.getPath().toString(), ((LwM2mObject) node).toString());
if (singleResource.getType() == ResourceModel.Type.STRING) { } else if (node instanceof LwM2mObjectInstance) {
valueLength = ((String) singleResource.getValue()).length(); msg = String.format("%s: Update finished successfully: Lwm2m code - %d Source path: %s value: %s",
value = ((String) singleResource.getValue()) LOG_LW2M_INFO, response.getCode().getCode(), request.getPath().toString(), ((LwM2mObjectInstance) node).prettyPrint());
.substring(Math.min(valueLength, config.getLogMaxLength())); } else if (node instanceof LwM2mSingleResource) {
LwM2mSingleResource singleResource = (LwM2mSingleResource) node;
if (singleResource.getType() == ResourceModel.Type.STRING || singleResource.getType() == ResourceModel.Type.OPAQUE) {
int valueLength;
if (singleResource.getType() == ResourceModel.Type.STRING) {
valueLength = ((String) singleResource.getValue()).length();
value = ((String) singleResource.getValue())
.substring(Math.min(valueLength, config.getLogMaxLength()));
} else {
valueLength = ((byte[]) singleResource.getValue()).length;
value = new String(Arrays.copyOf(((byte[]) singleResource.getValue()),
Math.min(valueLength, config.getLogMaxLength())));
}
value = valueLength > config.getLogMaxLength() ? value + "..." : value;
msg = String.format("%s: Update finished successfully: Lwm2m code - %d Resource path: %s length: %s value: %s",
LOG_LW2M_INFO, response.getCode().getCode(), request.getPath().toString(), valueLength, value);
} else { } else {
valueLength = ((byte[]) singleResource.getValue()).length; value = this.converter.convertValue(singleResource.getValue(),
value = new String(Arrays.copyOf(((byte[]) singleResource.getValue()), singleResource.getType(), ResourceModel.Type.STRING, request.getPath());
Math.min(valueLength, config.getLogMaxLength()))); msg = String.format("%s: Update finished successfully. Lwm2m code: %d Resource path: %s value: %s",
LOG_LW2M_INFO, response.getCode().getCode(), request.getPath().toString(), value);
} }
value = valueLength > config.getLogMaxLength() ? value + "..." : value;
msg = String.format("%s: Update finished successfully: Lwm2m code - %d Resource path: %s length: %s value: %s",
LOG_LW2M_INFO, response.getCode().getCode(), request.getPath().toString(), valueLength, value);
} else {
value = this.converter.convertValue(singleResource.getValue(),
singleResource.getType(), ResourceModel.Type.STRING, request.getPath());
msg = String.format("%s: Update finished successfully. Lwm2m code: %d Resource path: %s value: %s",
LOG_LW2M_INFO, response.getCode().getCode(), request.getPath().toString(), value);
} }
if (msg != null) { if (msg != null) {
handler.sendLogsToThingsboard(msg, registration.getId()); handler.sendLogsToThingsboard(msg, registration.getId());
@ -538,11 +554,11 @@ public class LwM2mTransportRequest {
LwM2mClient lwM2MClient = this.lwM2mClientContext.getClientByRegistrationId(registration.getId()); LwM2mClient lwM2MClient = this.lwM2mClientContext.getClientByRegistrationId(registration.getId());
if (request.getPath().toString().equals(FW_PACKAGE_ID) && lwM2MClient.getFwUpdate() != null) { if (request.getPath().toString().equals(FW_PACKAGE_ID) && lwM2MClient.getFwUpdate() != null) {
lwM2MClient.getFwUpdate().setStateUpdate(DOWNLOADED.name()); lwM2MClient.getFwUpdate().setStateUpdate(DOWNLOADED.name());
lwM2MClient.getFwUpdate().sendLogs(WRITE_REPLACE.name(), LOG_LW2M_INFO, null); lwM2MClient.getFwUpdate().sendLogs(this.handler, WRITE_REPLACE.name(), LOG_LW2M_INFO, null);
} }
if (request.getPath().toString().equals(SW_PACKAGE_ID) && lwM2MClient.getSwUpdate() != null) { if (request.getPath().toString().equals(SW_PACKAGE_ID) && lwM2MClient.getSwUpdate() != null) {
lwM2MClient.getSwUpdate().setStateUpdate(DOWNLOADED.name()); lwM2MClient.getSwUpdate().setStateUpdate(DOWNLOADED.name());
lwM2MClient.getSwUpdate().sendLogs(WRITE_REPLACE.name(), LOG_LW2M_INFO, null); lwM2MClient.getSwUpdate().sendLogs(this.handler,WRITE_REPLACE.name(), LOG_LW2M_INFO, null);
} }
} }
@ -553,21 +569,21 @@ public class LwM2mTransportRequest {
LwM2mClient lwM2MClient = this.lwM2mClientContext.getClientByRegistrationId(registration.getId()); LwM2mClient lwM2MClient = this.lwM2mClientContext.getClientByRegistrationId(registration.getId());
if (request.getPath().toString().equals(FW_PACKAGE_ID) && lwM2MClient.getFwUpdate() != null) { if (request.getPath().toString().equals(FW_PACKAGE_ID) && lwM2MClient.getFwUpdate() != null) {
lwM2MClient.getFwUpdate().setStateUpdate(FAILED.name()); lwM2MClient.getFwUpdate().setStateUpdate(FAILED.name());
lwM2MClient.getFwUpdate().sendLogs(WRITE_REPLACE.name(), LOG_LW2M_ERROR, msgError); lwM2MClient.getFwUpdate().sendLogs(this.handler, WRITE_REPLACE.name(), LOG_LW2M_ERROR, msgError);
} }
if (request.getPath().toString().equals(SW_PACKAGE_ID) && lwM2MClient.getSwUpdate() != null) { if (request.getPath().toString().equals(SW_PACKAGE_ID) && lwM2MClient.getSwUpdate() != null) {
lwM2MClient.getSwUpdate().setStateUpdate(FAILED.name()); lwM2MClient.getSwUpdate().setStateUpdate(FAILED.name());
lwM2MClient.getSwUpdate().sendLogs(WRITE_REPLACE.name(), LOG_LW2M_ERROR, msgError); lwM2MClient.getSwUpdate().sendLogs(this.handler, WRITE_REPLACE.name(), LOG_LW2M_ERROR, msgError);
} }
} }
private void afterExecuteFwSwUpdateError(Registration registration, DownlinkRequest request, String msgError) { private void afterExecuteFwSwUpdateError(Registration registration, DownlinkRequest request, String msgError) {
LwM2mClient lwM2MClient = this.lwM2mClientContext.getClientByRegistrationId(registration.getId()); LwM2mClient lwM2MClient = this.lwM2mClientContext.getClientByRegistrationId(registration.getId());
if (request.getPath().toString().equals(FW_UPDATE_ID) && lwM2MClient.getFwUpdate() != null) { if (request.getPath().toString().equals(FW_UPDATE_ID) && lwM2MClient.getFwUpdate() != null) {
lwM2MClient.getFwUpdate().sendLogs(EXECUTE.name(), LOG_LW2M_ERROR, msgError); lwM2MClient.getFwUpdate().sendLogs(this.handler, EXECUTE.name(), LOG_LW2M_ERROR, msgError);
} }
if (request.getPath().toString().equals(SW_INSTALL_ID) && lwM2MClient.getSwUpdate() != null) { if (request.getPath().toString().equals(SW_INSTALL_ID) && lwM2MClient.getSwUpdate() != null) {
lwM2MClient.getSwUpdate().sendLogs(EXECUTE.name(), LOG_LW2M_ERROR, msgError); lwM2MClient.getSwUpdate().sendLogs(this.handler, EXECUTE.name(), LOG_LW2M_ERROR, msgError);
} }
} }

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

@ -61,9 +61,12 @@ import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import static org.eclipse.leshan.core.attributes.Attribute.DIMENSION; 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.MAXIMUM_PERIOD;
import static org.eclipse.leshan.core.attributes.Attribute.MINIMUM_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.OBJECT_VERSION;
import static org.eclipse.leshan.core.attributes.Attribute.STEP;
import static org.eclipse.leshan.core.model.ResourceModel.Type.BOOLEAN; import static org.eclipse.leshan.core.model.ResourceModel.Type.BOOLEAN;
import static org.eclipse.leshan.core.model.ResourceModel.Type.FLOAT; import static org.eclipse.leshan.core.model.ResourceModel.Type.FLOAT;
import static org.eclipse.leshan.core.model.ResourceModel.Type.INTEGER; import static org.eclipse.leshan.core.model.ResourceModel.Type.INTEGER;
@ -104,8 +107,7 @@ public class LwM2mTransportUtil {
public static final long DEFAULT_TIMEOUT = 2 * 60 * 1000L; // 2min in ms public static final long DEFAULT_TIMEOUT = 2 * 60 * 1000L; // 2min in ms
public static final String public static final String LOG_LW2M_TELEMETRY = "logLwm2m";
LOG_LW2M_TELEMETRY = "LwM2MLog";
public static final String LOG_LW2M_INFO = "info"; public static final String LOG_LW2M_INFO = "info";
public static final String LOG_LW2M_ERROR = "error"; public static final String LOG_LW2M_ERROR = "error";
public static final String LOG_LW2M_WARN = "warn"; public static final String LOG_LW2M_WARN = "warn";
@ -117,6 +119,23 @@ public class LwM2mTransportUtil {
public static final String CLIENT_NOT_AUTHORIZED = "Client not authorized"; public static final String CLIENT_NOT_AUTHORIZED = "Client not authorized";
public static final String LWM2M_VERSION_DEFAULT = "1.0"; public static final String LWM2M_VERSION_DEFAULT = "1.0";
// RPC
public static final String TYPE_OPER_KEY = "typeOper";
public static final String TARGET_ID_VER_KEY = "targetIdVer";
public static final String KEY_NAME_KEY = "key";
public static final String VALUE_KEY = "value";
public static final String PARAMS_KEY = "params";
public static final String SEPARATOR_KEY = ":";
public static final String FINISH_VALUE_KEY = ",";
public static final String START_JSON_KEY = "{";
public static final String FINISH_JSON_KEY = "}";
// public static final String contentFormatNameKey = "contentFormatName";
public static final String INFO_KEY = "info";
// public static final String TIME_OUT_IN_MS = "timeOutInMs";
public static final String RESULT_KEY = "result";
public static final String ERROR_KEY = "error";
public static final String METHOD_KEY = "methodName";
// FirmWare // FirmWare
public static final String FW_UPDATE = "Firmware update"; public static final String FW_UPDATE = "Firmware update";
public static final Integer FW_ID = 5; public static final Integer FW_ID = 5;
@ -182,20 +201,21 @@ public class LwM2mTransportUtil {
*/ */
READ(0, "Read"), READ(0, "Read"),
DISCOVER(1, "Discover"), DISCOVER(1, "Discover"),
DISCOVER_All(2, "DiscoverAll"), DISCOVER_ALL(2, "DiscoverAll"),
OBSERVE_READ_ALL(3, "ObserveReadAll"), OBSERVE_READ_ALL(3, "ObserveReadAll"),
/** /**
* POST * POST
*/ */
OBSERVE(4, "Observe"), OBSERVE(4, "Observe"),
OBSERVE_CANCEL(5, "ObserveCancel"), OBSERVE_CANCEL(5, "ObserveCancel"),
EXECUTE(6, "Execute"), OBSERVE_CANCEL_ALL(6, "ObserveCancelAll"),
EXECUTE(7, "Execute"),
/** /**
* Replaces the Object Instance or the Resource(s) with the new value provided in the Write operation. (see * Replaces the Object Instance or the Resource(s) with the new value provided in the Write operation. (see
* section 5.3.3 of the LW M2M spec). * section 5.3.3 of the LW M2M spec).
* if all resources are to be replaced * if all resources are to be replaced
*/ */
WRITE_REPLACE(7, "WriteReplace"), WRITE_REPLACE(8, "WriteReplace"),
/* /*
PUT PUT
*/ */
@ -204,18 +224,16 @@ public class LwM2mTransportUtil {
* 5.3.3 of the LW M2M spec). * 5.3.3 of the LW M2M spec).
* if this is a partial update request * if this is a partial update request
*/ */
WRITE_UPDATE(8, "WriteUpdate"), WRITE_UPDATE(9, "WriteUpdate"),
WRITE_ATTRIBUTES(9, "WriteAttributes"), WRITE_ATTRIBUTES(10, "WriteAttributes"),
DELETE(10, "Delete"), DELETE(11, "Delete");
// only for RPC // only for RPC
FW_READ_INFO(11, "FirmwareReadInfo"), // FW_READ_INFO(12, "FirmwareReadInfo"),
FW_UPDATE(12, "FirmwareUpdate"), // FW_UPDATE(13, "FirmwareUpdate"),
FW_UPDATE_URL(14, "FirmwareUpdateUrl"), // SW_READ_INFO(15, "SoftwareReadInfo"),
SW_READ_INFO(15, "SoftwareReadInfo"), // SW_UPDATE(16, "SoftwareUpdate"),
SW_UPDATE(16, "SoftwareUpdate"), // SW_UNINSTALL(18, "SoftwareUninstall");
SW_UPDATE_URL(17, "SoftwareUpdateUrl"),
SW_UNINSTALL(18, "SoftwareUninstall");
public int code; public int code;
public String type; public String type;
@ -817,26 +835,29 @@ public class LwM2mTransportUtil {
* Attribute pmax = new Attribute(MAXIMUM_PERIOD, "60"); * Attribute pmax = new Attribute(MAXIMUM_PERIOD, "60");
* Attribute [] attrs = {gt, st}; * Attribute [] attrs = {gt, st};
*/ */
public static DownlinkRequest createWriteAttributeRequest(String target, Object params) { public static DownlinkRequest createWriteAttributeRequest(String target, Object params, DefaultLwM2MTransportMsgHandler serviceImpl) {
AttributeSet attrSet = new AttributeSet(createWriteAttributes(params)); AttributeSet attrSet = new AttributeSet(createWriteAttributes(params, serviceImpl, target));
return attrSet.getAttributes().size() > 0 ? new WriteAttributesRequest(target, attrSet) : null; return attrSet.getAttributes().size() > 0 ? new WriteAttributesRequest(target, attrSet) : null;
} }
private static Attribute[] createWriteAttributes(Object params) { private static Attribute[] createWriteAttributes(Object params, DefaultLwM2MTransportMsgHandler serviceImpl, String target) {
List<Attribute> attributeLists = new ArrayList<>(); List<Attribute> attributeLists = new ArrayList<>();
ObjectMapper oMapper = new ObjectMapper(); ObjectMapper oMapper = new ObjectMapper();
Map<String, Object> map = oMapper.convertValue(params, ConcurrentHashMap.class); Map<String, Object> map = oMapper.convertValue(params, ConcurrentHashMap.class);
map.forEach((k, v) -> { map.forEach((k, v) -> {
if (!v.toString().isEmpty() || (v.toString().isEmpty() && OBJECT_VERSION.equals(k))) { if (StringUtils.trimToNull(v.toString()) != null) {
attributeLists.add(new Attribute(k, Object attrValue = convertWriteAttributes(k, v, serviceImpl, target);
(DIMENSION.equals(k) || MINIMUM_PERIOD.equals(k) || MAXIMUM_PERIOD.equals(k)) ? if (attrValue != null) {
((Double) v).longValue() : v)); Attribute attribute = createAttribute(k, attrValue);
if (attribute != null) {
attributeLists.add(new Attribute(k, attrValue));
}
}
} }
}); });
return attributeLists.toArray(Attribute[]::new); return attributeLists.toArray(Attribute[]::new);
} }
public static Set<String> convertJsonArrayToSet(JsonArray jsonArray) { public static Set<String> convertJsonArrayToSet(JsonArray jsonArray) {
List<String> attributeListOld = new Gson().fromJson(jsonArray, new TypeToken<List<String>>() { List<String> attributeListOld = new Gson().fromJson(jsonArray, new TypeToken<List<String>>() {
}.getType()); }.getType());
@ -863,4 +884,47 @@ public class LwM2mTransportUtil {
return null; return null;
} }
} }
public static LwM2mTypeOper setValidTypeOper(String typeOper) {
try {
return LwM2mTransportUtil.LwM2mTypeOper.fromLwLwM2mTypeOper(typeOper);
} catch (Exception e) {
return null;
}
}
public static Object convertWriteAttributes(String type, Object value, DefaultLwM2MTransportMsgHandler serviceImpl, String target) {
switch (type) {
/** Integer [0:255]; */
case DIMENSION:
Long dim = (Long) serviceImpl.converter.convertValue(value, equalsResourceTypeGetSimpleName(value), INTEGER, new LwM2mPath(target));
return dim >= 0 && dim <= 255 ? dim : null;
/**String;*/
case OBJECT_VERSION:
return serviceImpl.converter.convertValue(value, equalsResourceTypeGetSimpleName(value), STRING, new LwM2mPath(target));
/**INTEGER */
case MINIMUM_PERIOD:
case MAXIMUM_PERIOD:
return serviceImpl.converter.convertValue(value, equalsResourceTypeGetSimpleName(value), INTEGER, new LwM2mPath(target));
/**Float; */
case GREATER_THAN:
case LESSER_THAN:
case STEP:
if (value.getClass().getSimpleName().equals("String") ) {
value = Double.valueOf((String) value);
}
return serviceImpl.converter.convertValue(value, equalsResourceTypeGetSimpleName(value), FLOAT, new LwM2mPath(target));
default:
return null;
}
}
private static Attribute createAttribute(String key, Object attrValue) {
try {
return new Attribute(key, attrValue);
} catch (Exception e) {
log.error("CreateAttribute, not valid parameter key: [{}], attrValue: [{}], error: [{}]", key, attrValue, e.getMessage());
return null;
}
}
} }

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

@ -31,8 +31,8 @@ import org.eclipse.leshan.server.registration.Registration;
import org.eclipse.leshan.server.security.SecurityInfo; import org.eclipse.leshan.server.security.SecurityInfo;
import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.DeviceProfile; import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse;
import org.thingsboard.server.common.data.firmware.FirmwareType; import org.thingsboard.server.common.data.firmware.FirmwareType;
import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse;
import org.thingsboard.server.gen.transport.TransportProtos.SessionInfoProto; import org.thingsboard.server.gen.transport.TransportProtos.SessionInfoProto;
import org.thingsboard.server.gen.transport.TransportProtos.TsKvProto; import org.thingsboard.server.gen.transport.TransportProtos.TsKvProto;
import org.thingsboard.server.transport.lwm2m.server.DefaultLwM2MTransportMsgHandler; import org.thingsboard.server.transport.lwm2m.server.DefaultLwM2MTransportMsgHandler;
@ -117,7 +117,6 @@ public class LwM2mClient implements Cloneable {
this.pendingReadRequests = new CopyOnWriteArrayList<>(); this.pendingReadRequests = new CopyOnWriteArrayList<>();
this.resources = new ConcurrentHashMap<>(); this.resources = new ConcurrentHashMap<>();
this.profileId = profileId; this.profileId = profileId;
this.sessionId = sessionId;
this.init = false; this.init = false;
this.queuedRequests = new ConcurrentLinkedQueue<>(); this.queuedRequests = new ConcurrentLinkedQueue<>();
@ -194,17 +193,31 @@ public class LwM2mClient implements Cloneable {
public Object getResourceValue(String pathRezIdVer, String pathRezId) { public Object getResourceValue(String pathRezIdVer, String pathRezId) {
String pathRez = pathRezIdVer == null ? convertPathFromObjectIdToIdVer(pathRezId, this.registration) : pathRezIdVer; String pathRez = pathRezIdVer == null ? convertPathFromObjectIdToIdVer(pathRezId, this.registration) : pathRezIdVer;
if (this.resources.get(pathRez) != null) { if (this.resources.get(pathRez) != null) {
return this.resources.get(pathRez).getLwM2mResource().isMultiInstances() ? return this.resources.get(pathRez).getLwM2mResource().isMultiInstances() ?
this.resources.get(pathRez).getLwM2mResource().getValues() : this.resources.get(pathRez).getLwM2mResource().getValues() :
this.resources.get(pathRez).getLwM2mResource().getValue(); this.resources.get(pathRez).getLwM2mResource().getValue();
} }
return null; return null;
} }
public Object getResourceName (String pathRezIdVer, String pathRezId) { public Object getResourceNameByRezId(String pathRezIdVer, String pathRezId) {
String pathRez = pathRezIdVer == null ? convertPathFromObjectIdToIdVer(pathRezId, this.registration) : pathRezIdVer; String pathRez = pathRezIdVer == null ? convertPathFromObjectIdToIdVer(pathRezId, this.registration) : pathRezIdVer;
if (this.resources.get(pathRez) != null) { if (this.resources.get(pathRez) != null) {
return this.resources.get(pathRez).getResourceModel().name; return this.resources.get(pathRez).getResourceModel().name;
}
return null;
}
public String getRezIdByResourceNameAndObjectInstanceId(String resourceName, String pathObjectInstanceIdVer, LwM2mModelProvider modelProvider) {
LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(pathObjectInstanceIdVer));
if (pathIds.isObjectInstance()) {
Set<Integer> rezIds = modelProvider.getObjectModel(registration)
.getObjectModel(pathIds.getObjectId()).resources.entrySet()
.stream()
.filter(map -> resourceName.equals(map.getValue().name))
.map(map -> map.getKey())
.collect(Collectors.toSet());
return rezIds.size() > 0 ? String.valueOf(rezIds.stream().findFirst().get()) : null;
} }
return null; return null;
} }
@ -225,11 +238,11 @@ public class LwM2mClient implements Cloneable {
.getObjectModel(pathIds.getObjectId()) : null; .getObjectModel(pathIds.getObjectId()) : null;
} }
public String objectToString (LwM2mObject lwM2mObject, LwM2mValueConverterImpl converter, String pathIdVer) { public String objectToString(LwM2mObject lwM2mObject, LwM2mValueConverterImpl converter, String pathIdVer) {
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
builder.append("LwM2mObject [id=").append(lwM2mObject.getId()).append(", instances={"); builder.append("LwM2mObject [id=").append(lwM2mObject.getId()).append(", instances={");
lwM2mObject.getInstances().forEach((instId, inst) -> { lwM2mObject.getInstances().forEach((instId, inst) -> {
builder.append(instId).append("=").append(this.instanceToString(inst, converter, pathIdVer)).append(", "); builder.append(instId).append("=").append(this.instanceToString(inst, converter, pathIdVer)).append(", ");
}); });
int startInd = builder.lastIndexOf(", "); int startInd = builder.lastIndexOf(", ");
if (startInd > 0) { if (startInd > 0) {
@ -238,11 +251,12 @@ public class LwM2mClient implements Cloneable {
builder.append("}]"); builder.append("}]");
return builder.toString(); return builder.toString();
} }
public String instanceToString (LwM2mObjectInstance objectInstance, LwM2mValueConverterImpl converter, String pathIdVer) {
public String instanceToString(LwM2mObjectInstance objectInstance, LwM2mValueConverterImpl converter, String pathIdVer) {
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
builder.append("LwM2mObjectInstance [id=").append(objectInstance.getId()).append(", resources={"); builder.append("LwM2mObjectInstance [id=").append(objectInstance.getId()).append(", resources={");
objectInstance.getResources().forEach((resId, res) -> { objectInstance.getResources().forEach((resId, res) -> {
builder.append(resId).append("=").append(this.resourceToString (res, converter, pathIdVer)).append(", "); builder.append(resId).append("=").append(this.resourceToString(res, converter, pathIdVer)).append(", ");
}); });
int startInd = builder.lastIndexOf(", "); int startInd = builder.lastIndexOf(", ");
if (startInd > 0) { if (startInd > 0) {
@ -252,12 +266,11 @@ public class LwM2mClient implements Cloneable {
return builder.toString(); return builder.toString();
} }
public String resourceToString (LwM2mResource lwM2mResource, LwM2mValueConverterImpl converter, String pathIdVer) { public String resourceToString(LwM2mResource lwM2mResource, LwM2mValueConverterImpl converter, String pathIdVer) {
if (!OPAQUE.equals(lwM2mResource.getType())) { if (!OPAQUE.equals(lwM2mResource.getType())) {
return lwM2mResource.isMultiInstances() ? ((LwM2mMultipleResource) lwM2mResource).toString() : return lwM2mResource.isMultiInstances() ? ((LwM2mMultipleResource) lwM2mResource).toString() :
((LwM2mSingleResource) lwM2mResource).toString(); ((LwM2mSingleResource) lwM2mResource).toString();
} } else {
else {
return String.format("LwM2mSingleResource [id=%s, value=%s, type=%s]", lwM2mResource.getId(), return String.format("LwM2mSingleResource [id=%s, value=%s, type=%s]", lwM2mResource.getId(),
converter.convertValue(lwM2mResource.getValue(), converter.convertValue(lwM2mResource.getValue(),
OPAQUE, STRING, new LwM2mPath(convertPathFromIdVerToObjectId(pathIdVer))), lwM2mResource.getType().name()); OPAQUE, STRING, new LwM2mPath(convertPathFromIdVerToObjectId(pathIdVer))), lwM2mResource.getType().name());
@ -275,7 +288,8 @@ public class LwM2mClient implements Cloneable {
resources.add(LwM2mSingleResource.newResource(resId, converter.convertValue(params, resources.add(LwM2mSingleResource.newResource(resId, converter.convertValue(params,
equalsResourceTypeGetSimpleName(params), resourceModel.type, pathIds), resourceModel.type)); equalsResourceTypeGetSimpleName(params), resourceModel.type, pathIds), resourceModel.type));
}}); }
});
return resources; return resources;
} }
@ -291,7 +305,8 @@ public class LwM2mClient implements Cloneable {
resources.add(LwM2mSingleResource.newResource(resId, resources.add(LwM2mSingleResource.newResource(resId,
converter.convertValue(value, equalsResourceTypeGetSimpleName(value), resourceModel.type, pathIds), resourceModel.type)); converter.convertValue(value, equalsResourceTypeGetSimpleName(value), resourceModel.type, pathIds), resourceModel.type));
}}); }
});
return resources; return resources;
} }

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

@ -35,8 +35,6 @@ public interface LwM2mClientContext {
LwM2mClient getClient(TransportProtos.SessionInfoProto sessionInfo); LwM2mClient getClient(TransportProtos.SessionInfoProto sessionInfo);
LwM2mClient getClient(UUID sessionId);
LwM2mClient getOrRegister(Registration registration); LwM2mClient getOrRegister(Registration registration);
LwM2mClient registerOrUpdate(Registration registration); LwM2mClient registerOrUpdate(Registration registration);

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

@ -83,13 +83,11 @@ public class LwM2mClientContextImpl implements LwM2mClientContext {
@Override @Override
public LwM2mClient getClient(TransportProtos.SessionInfoProto sessionInfo) { public LwM2mClient getClient(TransportProtos.SessionInfoProto sessionInfo) {
return getClient(new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB())); return lwM2mClientsByEndpoint.values().stream().filter(c ->
} (new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB()))
.equals((new UUID(c.getSession().getSessionIdMSB(), c.getSession().getSessionIdLSB())))
@Override ).findAny().get();
public LwM2mClient getClient(UUID sessionId) {
//TODO: refactor this to search by sessionId efficiently.
return lwM2mClientsByEndpoint.values().stream().filter(c -> c.getSessionId().equals(sessionId)).findAny().get();
} }
@Override @Override

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

@ -286,7 +286,7 @@ public class LwM2mFwSwUpdate {
Long updateResult = (Long) this.lwM2MClient.getResourceValue(null, this.pathResultId); Long updateResult = (Long) this.lwM2MClient.getResourceValue(null, this.pathResultId);
String value = FIRMWARE.equals(this.type) ? LwM2mTransportUtil.UpdateResultFw.fromUpdateResultFwByCode(updateResult.intValue()).type : String value = FIRMWARE.equals(this.type) ? LwM2mTransportUtil.UpdateResultFw.fromUpdateResultFwByCode(updateResult.intValue()).type :
LwM2mTransportUtil.UpdateResultSw.fromUpdateResultSwByCode(updateResult.intValue()).type; LwM2mTransportUtil.UpdateResultSw.fromUpdateResultSwByCode(updateResult.intValue()).type;
String key = splitCamelCaseString((String) this.lwM2MClient.getResourceName(null, this.pathResultId)); String key = splitCamelCaseString((String) this.lwM2MClient.getResourceNameByRezId(null, this.pathResultId));
if (success) { if (success) {
this.stateUpdate = FirmwareUpdateStatus.UPDATED.name(); this.stateUpdate = FirmwareUpdateStatus.UPDATED.name();
this.sendLogs(handler, EXECUTE.name(), LOG_LW2M_INFO, null); this.sendLogs(handler, EXECUTE.name(), LOG_LW2M_INFO, null);

273
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/Lwm2mClientRpcRequest.java

@ -15,98 +15,265 @@
*/ */
package org.thingsboard.server.transport.lwm2m.server.client; package org.thingsboard.server.transport.lwm2m.server.client;
import com.google.gson.Gson;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import com.google.gson.reflect.TypeToken;
import lombok.Data; import lombok.Data;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.eclipse.leshan.core.request.ContentFormat; import org.apache.commons.lang3.StringUtils;
import org.eclipse.leshan.core.node.LwM2mPath;
import org.eclipse.leshan.server.registration.Registration; import org.eclipse.leshan.server.registration.Registration;
import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.gen.transport.TransportProtos;
import org.thingsboard.server.gen.transport.TransportProtos.SessionInfoProto; import org.thingsboard.server.transport.lwm2m.server.DefaultLwM2MTransportMsgHandler;
import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeoutException;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.ERROR_KEY;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FINISH_JSON_KEY;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FINISH_VALUE_KEY;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.INFO_KEY;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.KEY_NAME_KEY;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.DISCOVER_ALL;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.EXECUTE;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.OBSERVE_CANCEL;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.OBSERVE_READ_ALL;
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.LwM2mTypeOper.WRITE_UPDATE;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.METHOD_KEY;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.PARAMS_KEY;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.RESULT_KEY;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SEPARATOR_KEY;
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.validPathIdVer; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.validPathIdVer;
@Slf4j @Slf4j
@Data @Data
public class Lwm2mClientRpcRequest { public class Lwm2mClientRpcRequest {
public final String targetIdVerKey = "targetIdVer";
public final String keyNameKey = "key"; private Registration registration;
public final String typeOperKey = "typeOper"; private TransportProtos.SessionInfoProto sessionInfo;
public final String contentFormatNameKey = "contentFormatName"; private String bodyParams;
public final String valueKey = "value"; private int requestId;
public final String infoKey = "info";
public final String paramsKey = "params";
public final String timeoutInMsKey = "timeOutInMs";
public final String resultKey = "result";
public final String errorKey = "error";
public final String methodKey = "methodName";
private LwM2mTypeOper typeOper; private LwM2mTypeOper typeOper;
private String key;
private String targetIdVer; private String targetIdVer;
private String contentFormatName;
private long timeoutInMs;
private Object value; private Object value;
private ConcurrentHashMap<String, Object> params; private Map<String, Object> params;
private SessionInfoProto sessionInfo;
private int requestId;
private String errorMsg; private String errorMsg;
private String valueMsg; private String valueMsg;
private String infoMsg; private String infoMsg;
private String responseCode; private String responseCode;
public void setValidTypeOper(String typeOper) { public Lwm2mClientRpcRequest() {
}
public Lwm2mClientRpcRequest(LwM2mTypeOper lwM2mTypeOper, String bodyParams, int requestId,
TransportProtos.SessionInfoProto sessionInfo, Registration registration, DefaultLwM2MTransportMsgHandler handler) {
this.registration = registration;
this.sessionInfo = sessionInfo;
this.requestId = requestId;
if (lwM2mTypeOper != null) {
this.typeOper = lwM2mTypeOper;
} else {
this.errorMsg = METHOD_KEY + " - " + typeOper + " is not valid.";
}
if (this.errorMsg == null && !bodyParams.equals("null")) {
this.bodyParams = bodyParams;
this.init(handler);
}
}
public TransportProtos.ToDeviceRpcResponseMsg getDeviceRpcResponseResultMsg() {
JsonObject payloadResp = new JsonObject();
payloadResp.addProperty(RESULT_KEY, this.responseCode);
if (this.errorMsg != null) {
payloadResp.addProperty(ERROR_KEY, this.errorMsg);
} else if (this.valueMsg != null) {
payloadResp.addProperty(VALUE_KEY, this.valueMsg);
} else if (this.infoMsg != null) {
payloadResp.addProperty(INFO_KEY, this.infoMsg);
}
return TransportProtos.ToDeviceRpcResponseMsg.newBuilder()
.setPayload(payloadResp.getAsJsonObject().toString())
.setRequestId(this.requestId)
.build();
}
private void init(DefaultLwM2MTransportMsgHandler handler) {
try { try {
this.typeOper = LwM2mTypeOper.fromLwLwM2mTypeOper(typeOper); // #1
if (this.bodyParams.contains(KEY_NAME_KEY)) {
String targetIdVerStr = this.getValueKeyFromBody(KEY_NAME_KEY);
if (targetIdVerStr != null) {
String targetIdVer = handler.getPresentPathIntoProfile(sessionInfo, targetIdVerStr);
if (targetIdVer != null) {
this.targetIdVer = targetIdVer;
this.setInfoMsg(String.format("Changed by: key - %s, pathIdVer - %s",
targetIdVerStr, targetIdVer));
}
}
}
if (this.getTargetIdVer() == null && this.bodyParams.contains(TARGET_ID_VER_KEY)) {
this.setValidTargetIdVerKey();
}
if (this.bodyParams.contains(VALUE_KEY)) {
this.value = this.getValueKeyFromBody(VALUE_KEY);
}
try {
if (this.bodyParams.contains(PARAMS_KEY)) {
this.setValidParamsKey(handler);
}
} catch (Exception e) {
this.setErrorMsg(String.format("Params of request is bad Json format. %s", e.getMessage()));
}
if (this.getTargetIdVer() == null
&& !(OBSERVE_READ_ALL == this.getTypeOper()
|| DISCOVER_ALL == this.getTypeOper()
|| OBSERVE_CANCEL == this.getTypeOper())) {
this.setErrorMsg(TARGET_ID_VER_KEY + " and " +
KEY_NAME_KEY + " is null or bad format");
}
/**
* EXECUTE && WRITE_REPLACE - only for Resource or ResourceInstance
*/
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())) {
this.setErrorMsg("Invalid parameter " + TARGET_ID_VER_KEY
+ ". Only Resource or ResourceInstance can be this operation");
}
} catch (Exception e) { } catch (Exception e) {
this.errorMsg = this.methodKey + " - " + typeOper + " is not valid."; this.setErrorMsg(String.format("Bad format request. %s", e.getMessage()));
} }
} }
public void setValidContentFormatName(JsonObject rpcRequest) { private void setValidTargetIdVerKey() {
String targetIdVerStr = this.getValueKeyFromBody(TARGET_ID_VER_KEY);
// targetIdVer without ver - ok
try { try {
if (ContentFormat.fromName(rpcRequest.get(this.contentFormatNameKey).getAsString()) != null) { // targetIdVer with/without ver - ok
this.contentFormatName = rpcRequest.get(this.contentFormatNameKey).getAsString(); this.targetIdVer = validPathIdVer(targetIdVerStr, this.registration);
} else { if (this.targetIdVer != null) {
this.errorMsg = this.contentFormatNameKey + " - " + rpcRequest.get(this.contentFormatNameKey).getAsString() + " is not valid."; this.infoMsg = String.format("Changed by: pathIdVer - %s", this.targetIdVer);
} }
} catch (Exception e) { } catch (Exception e) {
this.errorMsg = this.contentFormatNameKey + " - " + rpcRequest.get(this.contentFormatNameKey).getAsString() + " is not valid."; if (this.targetIdVer == null) {
this.errorMsg = TARGET_ID_VER_KEY + " - " + targetIdVerStr + " is not valid.";
}
} }
} }
public void setValidTargetIdVerKey(JsonObject rpcRequest, Registration registration) { private void setValidParamsKey(DefaultLwM2MTransportMsgHandler handler) {
if (rpcRequest.has(this.targetIdVerKey)) { String paramsStr = this.getValueKeyFromBody(PARAMS_KEY);
String targetIdVerStr = rpcRequest.get(targetIdVerKey).getAsString(); if (paramsStr != null) {
// targetIdVer without ver - ok String params2Json =
try { START_JSON_KEY
// targetIdVer with/without ver - ok + "\""
this.targetIdVer = validPathIdVer(targetIdVerStr, registration); + paramsStr
.replaceAll(SEPARATOR_KEY, "\"" + SEPARATOR_KEY + "\"")
.replaceAll(FINISH_VALUE_KEY, "\"" + FINISH_VALUE_KEY + "\"")
+ "\""
+ FINISH_JSON_KEY;
// jsonObject
Map<String, Object> params = new Gson().fromJson(params2Json, new TypeToken<ConcurrentHashMap<String, Object>>() {
}.getType());
if (WRITE_UPDATE == this.getTypeOper()) {
if (this.targetIdVer != null) { if (this.targetIdVer != null) {
this.infoMsg = String.format("Changed by: pathIdVer - %s", this.targetIdVer); Map<String, Object> paramsResourceId = this.convertParamsToResourceId((ConcurrentHashMap<String, Object>) params, handler);
} if (paramsResourceId.size() > 0) {
} catch (Exception e) { this.setParams(paramsResourceId);
if (this.targetIdVer == null) { }
this.errorMsg = this.targetIdVerKey + " - " + targetIdVerStr + " is not valid.";
} }
} else if (WRITE_ATTRIBUTES == this.getTypeOper()) {
this.setParams(params);
} }
} }
} }
public TransportProtos.ToDeviceRpcResponseMsg getDeviceRpcResponseResultMsg() { private String getValueKeyFromBody(String key) {
JsonObject payloadResp = new JsonObject(); String valueKey = null;
payloadResp.addProperty(this.resultKey, this.responseCode); int startInd = -1;
if (this.errorMsg != null) { int finishInd = -1;
payloadResp.addProperty(this.errorKey, this.errorMsg); try {
} else if (this.valueMsg != null) { switch (key) {
payloadResp.addProperty(this.valueKey, this.valueMsg); case KEY_NAME_KEY:
} else if (this.infoMsg != null) { case TARGET_ID_VER_KEY:
payloadResp.addProperty(this.infoKey, this.infoMsg); case VALUE_KEY:
startInd = this.bodyParams.indexOf(SEPARATOR_KEY, this.bodyParams.indexOf(key));
finishInd = this.bodyParams.indexOf(FINISH_VALUE_KEY, this.bodyParams.indexOf(key));
if (startInd >= 0 && finishInd < 0) {
finishInd = this.bodyParams.indexOf(FINISH_JSON_KEY, this.bodyParams.indexOf(key));
}
break;
case PARAMS_KEY:
startInd = this.bodyParams.indexOf(START_JSON_KEY, this.bodyParams.indexOf(key));
finishInd = this.bodyParams.indexOf(FINISH_JSON_KEY, this.bodyParams.indexOf(key));
}
if (startInd >= 0 && finishInd > 0) {
valueKey = this.bodyParams.substring(startInd + 1, finishInd);
}
} catch (Exception e) {
log.error("", new TimeoutException());
} }
return TransportProtos.ToDeviceRpcResponseMsg.newBuilder() /**
.setPayload(payloadResp.getAsJsonObject().toString()) * ReplaceAll "\""
.setRequestId(this.requestId) */
.build(); if (StringUtils.trimToNull(valueKey) != null) {
char[] chars = valueKey.toCharArray();
for (int i = 0; i < chars.length; i++) {
if (chars[i] == 92 || chars[i] == 34) chars[i] = 32;
}
return key.equals(PARAMS_KEY) ? String.valueOf(chars) : String.valueOf(chars).replaceAll(" ", "");
}
return null;
}
private ConcurrentHashMap<String, Object> convertParamsToResourceId(ConcurrentHashMap<String, Object> params,
DefaultLwM2MTransportMsgHandler serviceImpl) {
Map<String, Object> paramsIdVer = new ConcurrentHashMap<>();
LwM2mPath targetId = new LwM2mPath(Objects.requireNonNull(convertPathFromIdVerToObjectId(this.targetIdVer)));
if (targetId.isObjectInstance()) {
params.forEach((k, v) -> {
try {
int id = Integer.parseInt(k);
paramsIdVer.put(String.valueOf(id), v);
} catch (NumberFormatException e) {
String targetIdVer = serviceImpl.getPresentPathIntoProfile(sessionInfo, k);
if (targetIdVer != null) {
LwM2mPath lwM2mPath = new LwM2mPath(Objects.requireNonNull(convertPathFromIdVerToObjectId(targetIdVer)));
paramsIdVer.put(String.valueOf(lwM2mPath.getResourceId()), v);
}
/** WRITE_UPDATE*/
else {
String rezId = this.getRezIdByResourceNameAndObjectInstanceId(k, serviceImpl);
if (rezId != null) {
paramsIdVer.put(rezId, v);
}
}
}
});
}
return (ConcurrentHashMap<String, Object>) paramsIdVer;
}
private String getRezIdByResourceNameAndObjectInstanceId(String resourceName, DefaultLwM2MTransportMsgHandler handler) {
LwM2mClient lwM2mClient = handler.clientContext.getClient(this.sessionInfo);
return lwM2mClient != null ?
lwM2mClient.getRezIdByResourceNameAndObjectInstanceId(resourceName, this.targetIdVer, handler.config.getModelProvider()) :
null;
} }
} }

Loading…
Cancel
Save