First iteration of downlink handler refactoring

This commit is contained in:
Andrii Shvaika 2021-06-10 19:40:13 +03:00
parent f7ab3a21b2
commit 7e3087e107
8 changed files with 370 additions and 260 deletions

View File

@ -132,13 +132,13 @@ public class DefaultLwM2MUplinkMsgHandler implements LwM2mUplinkMsgHandler {
private final LwM2MJsonAdaptor adaptor; private final LwM2MJsonAdaptor adaptor;
private final TbLwM2MDtlsSessionStore sessionStore; private final TbLwM2MDtlsSessionStore sessionStore;
public final LwM2mClientContext clientContext; public final LwM2mClientContext clientContext;
public final DefaultLwM2mDownlinkMsgHandler defaultLwM2MDownlinkMsgHandler; public final LwM2mDownlinkMsgHandler defaultLwM2MDownlinkMsgHandler;
private final Map<UUID, Long> rpcSubscriptions; private final Map<UUID, Long> rpcSubscriptions;
public final Map<String, Integer> firmwareUpdateState; public final Map<String, Integer> firmwareUpdateState;
public DefaultLwM2MUplinkMsgHandler(TransportService transportService, LwM2MTransportServerConfig config, LwM2mTransportServerHelper helper, public DefaultLwM2MUplinkMsgHandler(TransportService transportService, LwM2MTransportServerConfig config, LwM2mTransportServerHelper helper,
LwM2mClientContext clientContext, LwM2mClientContext clientContext,
@Lazy DefaultLwM2mDownlinkMsgHandler defaultLwM2MDownlinkMsgHandler, @Lazy LwM2mDownlinkMsgHandler defaultLwM2MDownlinkMsgHandler,
OtaPackageDataCache otaPackageDataCache, OtaPackageDataCache otaPackageDataCache,
LwM2mTransportContext context, LwM2MJsonAdaptor adaptor, TbLwM2MDtlsSessionStore sessionStore) { LwM2mTransportContext context, LwM2MJsonAdaptor adaptor, TbLwM2MDtlsSessionStore sessionStore) {
this.transportService = transportService; this.transportService = transportService;
@ -291,8 +291,7 @@ public class DefaultLwM2MUplinkMsgHandler implements LwM2mUplinkMsgHandler {
if (registration != null) { if (registration != null) {
LwM2mClient client = clientContext.getClientByEndpoint(registration.getEndpoint()); LwM2mClient client = clientContext.getClientByEndpoint(registration.getEndpoint());
if (client != null && client.getRegistration() != null && client.getRegistration().getId().equals(registration.getId())) { if (client != null && client.getRegistration() != null && client.getRegistration().getId().equals(registration.getId())) {
this.defaultLwM2MDownlinkMsgHandler.sendAllRequest(client, null, OBSERVE_CANCEL_ALL, defaultLwM2MDownlinkMsgHandler.sendCancelAllRequest(client, this.config.getTimeout(), null);
null, null, this.config.getTimeout(), null);
} }
} }
} }
@ -595,8 +594,7 @@ public class DefaultLwM2MUplinkMsgHandler implements LwM2mUplinkMsgHandler {
if (LwM2mTransportUtil.LwM2MClientStrategy.CLIENT_STRATEGY_2.code == profile.getClientLwM2mSettings().getClientOnlyObserveAfterConnect()) { if (LwM2mTransportUtil.LwM2MClientStrategy.CLIENT_STRATEGY_2.code == profile.getClientLwM2mSettings().getClientOnlyObserveAfterConnect()) {
// #2 // #2
lwM2MClient.getPendingReadRequests().addAll(supportedObjects); lwM2MClient.getPendingReadRequests().addAll(supportedObjects);
supportedObjects.forEach(path -> defaultLwM2MDownlinkMsgHandler.sendAllRequest(lwM2MClient, path, READ, supportedObjects.forEach(path -> defaultLwM2MDownlinkMsgHandler.sendReadRequest(lwM2MClient, path, this.config.getTimeout()));
null, this.config.getTimeout(), null));
} }
// #1 // #1
this.sendReadRequests(lwM2MClient, profile, supportedObjects); this.sendReadRequests(lwM2MClient, profile, supportedObjects);
@ -640,24 +638,6 @@ public class DefaultLwM2MUplinkMsgHandler implements LwM2mUplinkMsgHandler {
targetIds.forEach(targetId -> defaultLwM2MDownlinkMsgHandler.sendDiscoverRequest(lwM2MClient, targetId, this.config.getTimeout())); targetIds.forEach(targetId -> defaultLwM2MDownlinkMsgHandler.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;
defaultLwM2MDownlinkMsgHandler.sendAllRequest(lwM2MClient, target, operationType, additionalParams, this.config.getTimeout(), null);
});
if (OBSERVE.equals(operationType)) {
lwM2MClient.initReadValue(this, null);
}
}
}
}
/** /**
* @param registration - * @param registration -
* @param lwM2mObject - * @param lwM2mObject -
@ -955,56 +935,32 @@ public class DefaultLwM2MUplinkMsgHandler implements LwM2mUplinkMsgHandler {
if (!newObjectsToRead.isEmpty()) { if (!newObjectsToRead.isEmpty()) {
Set<String> newObjectsToReadButNotNewInObserve = diffSets(observeToAdd, newObjectsToRead); Set<String> newObjectsToReadButNotNewInObserve = diffSets(observeToAdd, newObjectsToRead);
// update value in Resources // update value in Resources
if(!newObjectsToReadButNotNewInObserve.isEmpty()) { for (String targetId : newObjectsToReadButNotNewInObserve) {
clients.forEach(client -> this.readObserveFromProfile(client, newObjectsToReadButNotNewInObserve, READ)); clients.forEach(client -> defaultLwM2MDownlinkMsgHandler.sendReadRequest(client, targetId, this.config.getTimeout()));
} }
} }
// Calculating difference between old and new flags. // Calculating difference between old and new flags.
if(!observeToAdd.isEmpty()){ if (!observeToAdd.isEmpty()) {
clients.forEach(client -> this.readObserveFromProfile(client, observeToAdd, OBSERVE)); for (String targetId : observeToAdd) {
clients.forEach(client -> defaultLwM2MDownlinkMsgHandler.sendObserveRequest(client, targetId, this.config.getTimeout()));
}
} }
if(!observeToRemove.isEmpty()){ if (!observeToRemove.isEmpty()) {
clients.forEach(client -> this.cancelObserveFromProfile(client, observeToRemove)); for (String targetId : observeToRemove) {
clients.forEach(client -> defaultLwM2MDownlinkMsgHandler.sendCancelObserveRequest(client, targetId, this.config.getTimeout(), null));
}
} }
} }
} }
/** /**
Returns new set with elements that are present in set B(new) but absent in set A(old). Returns new set with elements that are present in set B(new) but absent in set A(old).
*/ */
private static <T> Set<T> diffSets(Set<T> a, Set<T> b){ private static <T> Set<T> diffSets(Set<T> a, Set<T> b) {
return b.stream().filter(p -> !a.contains(p)).collect(Collectors.toSet()); return b.stream().filter(p -> !a.contains(p)).collect(Collectors.toSet());
} }
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;
}
/**
* Update Resource value after change RezAttrTelemetry in config Profile
* send response Read to Client and add path to pathResAttrTelemetry in LwM2MClient.getAttrTelemetryObserveValue()
*
* @param targets - path Resources == [ "/2/0/0", "/2/0/1"]
*/
private void readObserveFromProfile(LwM2mClient client, Set<String> targets, LwM2mTypeOper typeOper) {
targets.forEach(target -> {
LwM2mPath pathIds = new LwM2mPath(fromVersionedIdToObjectId(target));
if (pathIds.isResource()) {
if (READ.equals(typeOper)) {
defaultLwM2MDownlinkMsgHandler.sendAllRequest(client, target, typeOper,
null, this.config.getTimeout(), null);
} else if (OBSERVE.equals(typeOper)) {
defaultLwM2MDownlinkMsgHandler.sendAllRequest(client, target, typeOper,
null, this.config.getTimeout(), null);
}
}
});
}
private ParametersAnalyzeResult getAnalyzerKeyName(Map<String, String> keyNameOld, Map<String, String> keyNameNew) { private ParametersAnalyzeResult getAnalyzerKeyName(Map<String, String> keyNameOld, Map<String, String> keyNameNew) {
ParametersAnalyzeResult analyzerParameters = new ParametersAnalyzeResult(); ParametersAnalyzeResult analyzerParameters = new ParametersAnalyzeResult();
Set<String> paths = keyNameNew.entrySet() Set<String> paths = keyNameNew.entrySet()
@ -1058,24 +1014,15 @@ public class DefaultLwM2MUplinkMsgHandler implements LwM2mUplinkMsgHandler {
} }
} }
private void cancelObserveFromProfile(LwM2mClient lwM2mClient, Set<String> paramAnallyzer) { private void updateResourcesValueToClient(LwM2mClient lwM2MClient, Object valueOld, Object newValue, String path) {
paramAnallyzer.forEach(pathIdVer -> { if (newValue != null && (valueOld == null || !newValue.toString().equals(valueOld.toString()))) {
if (this.getResourceValueFromLwM2MClient(lwM2mClient, pathIdVer) != null) { defaultLwM2MDownlinkMsgHandler.sendWriteReplaceRequest(lwM2MClient, path, newValue, this.config.getTimeout(), null);
defaultLwM2MDownlinkMsgHandler.sendAllRequest(lwM2mClient, pathIdVer, OBSERVE_CANCEL, null, this.config.getTimeout(), null);
}
}
);
}
private void updateResourcesValueToClient(LwM2mClient lwM2MClient, Object valueOld, Object valueNew, String path) {
if (valueNew != null && (valueOld == null || !valueNew.toString().equals(valueOld.toString()))) {
defaultLwM2MDownlinkMsgHandler.sendAllRequest(lwM2MClient, path, WRITE_REPLACE, valueNew, this.config.getTimeout(), null);
} else { } else {
log.error("Failed update resource [{}] [{}]", path, valueNew); log.error("Failed update resource [{}] [{}]", path, newValue);
String logMsg = String.format("%s: Failed update resource path - %s value - %s. Value is not changed or bad", String logMsg = String.format("%s: Failed update resource path - %s value - %s. Value is not changed or bad",
LOG_LW2M_ERROR, path, valueNew); LOG_LW2M_ERROR, path, newValue);
this.sendLogsToThingsboard(lwM2MClient, logMsg); this.sendLogsToThingsboard(lwM2MClient, logMsg);
log.info("Failed update resource [{}] [{}]", path, valueNew); log.info("Failed update resource [{}] [{}]", path, newValue);
} }
} }

View File

@ -30,6 +30,7 @@ import org.eclipse.leshan.core.node.LwM2mPath;
import org.eclipse.leshan.core.node.LwM2mResource; import org.eclipse.leshan.core.node.LwM2mResource;
import org.eclipse.leshan.core.node.LwM2mSingleResource; import org.eclipse.leshan.core.node.LwM2mSingleResource;
import org.eclipse.leshan.core.node.ObjectLink; import org.eclipse.leshan.core.node.ObjectLink;
import org.eclipse.leshan.core.node.codec.CodecException;
import org.eclipse.leshan.core.observation.Observation; import org.eclipse.leshan.core.observation.Observation;
import org.eclipse.leshan.core.request.ContentFormat; import org.eclipse.leshan.core.request.ContentFormat;
import org.eclipse.leshan.core.request.DeleteRequest; import org.eclipse.leshan.core.request.DeleteRequest;
@ -53,13 +54,13 @@ import org.eclipse.leshan.core.util.Hex;
import org.eclipse.leshan.core.util.NamedThreadFactory; import org.eclipse.leshan.core.util.NamedThreadFactory;
import org.eclipse.leshan.server.registration.Registration; import org.eclipse.leshan.server.registration.Registration;
import org.springframework.stereotype.Service; 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.common.data.device.data.lwm2m.ObjectAttributes;
import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;
import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig; import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig;
import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient; 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.LwM2mClientRpcRequest; import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientRpcRequest;
import org.thingsboard.server.transport.lwm2m.server.downlink.DownlinkRequestCallback;
import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl; import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl;
import javax.annotation.PostConstruct; import javax.annotation.PostConstruct;
@ -79,16 +80,13 @@ import java.util.stream.Collectors;
import static org.eclipse.californium.core.coap.CoAP.ResponseCode.CONTENT; 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.BAD_REQUEST;
import static org.eclipse.leshan.core.ResponseCode.NOT_FOUND; 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.GREATER_THAN;
import static org.eclipse.leshan.core.attributes.Attribute.LESSER_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.STEP; 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.DOWNLOADED;
import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.FAILED; import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.FAILED;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportServerHelper.getContentFormatByResourceModelType;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.DEFAULT_TIMEOUT; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.DEFAULT_TIMEOUT;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_PACKAGE_5_ID; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_PACKAGE_5_ID;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_UPDATE_ID; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_UPDATE_ID;
@ -106,9 +104,9 @@ 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.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_INSTALL_ID;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SW_PACKAGE_ID; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SW_PACKAGE_ID;
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.convertPathFromObjectIdToIdVer;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.createWriteAttributeRequest; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.createWriteAttributeRequest;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.fromVersionedIdToObjectId;
@Slf4j @Slf4j
@Service @Service
@ -131,26 +129,30 @@ public class DefaultLwM2mDownlinkMsgHandler implements LwM2mDownlinkMsgHandler {
new NamedThreadFactory(String.format("LwM2M %s channel response after request", RESPONSE_REQUEST_CHANNEL))); new NamedThreadFactory(String.format("LwM2M %s channel response after request", RESPONSE_REQUEST_CHANNEL)));
} }
public void sendReadRequest(LwM2mClient lwM2MClient, String targetId, Long timeout) { @Override
sendReadRequest(lwM2MClient, targetId, lwM2MClient.getDefaultContentFormat(), timeout); public void sendReadRequest(LwM2mClient client, String targetId, Long timeout) {
sendReadRequest(client, targetId, client.getDefaultContentFormat(), timeout);
} }
public void sendReadRequest(LwM2mClient lwM2MClient, String targetId, ContentFormat contentFormat, Long timeout) { @Override
public void sendReadRequest(LwM2mClient client, String targetId, ContentFormat contentFormat, Long timeout) {
String objectId = fromVersionedIdToObjectId(targetId); String objectId = fromVersionedIdToObjectId(targetId);
if (objectId != null && lwM2MClient.isValidObjectVersion(targetId)) { if (objectId != null && client.isValidObjectVersion(targetId)) {
sendRequest(lwM2MClient, new ReadRequest(contentFormat, objectId), timeout); sendRequest(client, new ReadRequest(contentFormat, objectId), timeout);
} }
} }
public void sendObserveRequest(LwM2mClient lwM2MClient, String targetId, Long timeout) { @Override
sendObserveRequest(lwM2MClient, targetId, lwM2MClient.getDefaultContentFormat(), timeout); public void sendObserveRequest(LwM2mClient client, String targetId, Long timeout) {
sendObserveRequest(client, targetId, client.getDefaultContentFormat(), timeout);
} }
public void sendObserveRequest(LwM2mClient lwM2MClient, String targetId, ContentFormat contentFormat, Long timeout) { @Override
public void sendObserveRequest(LwM2mClient client, String targetId, ContentFormat contentFormat, Long timeout) {
String objectId = fromVersionedIdToObjectId(targetId); String objectId = fromVersionedIdToObjectId(targetId);
if (objectId != null && lwM2MClient.isValidObjectVersion(targetId)) { if (objectId != null && client.isValidObjectVersion(targetId)) {
LwM2mPath resultIds = new LwM2mPath(objectId); LwM2mPath resultIds = new LwM2mPath(objectId);
Set<Observation> observations = context.getServer().getObservationService().getObservations(lwM2MClient.getRegistration()); Set<Observation> observations = context.getServer().getObservationService().getObservations(client.getRegistration());
if (observations.stream().noneMatch(observation -> observation.getPath().equals(resultIds))) { if (observations.stream().noneMatch(observation -> observation.getPath().equals(resultIds))) {
ObserveRequest request; ObserveRequest request;
if (resultIds.isResource()) { if (resultIds.isResource()) {
@ -160,22 +162,68 @@ public class DefaultLwM2mDownlinkMsgHandler implements LwM2mDownlinkMsgHandler {
} else { } else {
request = new ObserveRequest(contentFormat, resultIds.getObjectId()); request = new ObserveRequest(contentFormat, resultIds.getObjectId());
} }
log.info("[{}] Send observation: {}.", lwM2MClient.getEndpoint(), targetId); log.info("[{}] Send observation: {}.", client.getEndpoint(), targetId);
sendRequest(lwM2MClient, request, timeout); sendRequest(client, request, timeout);
} }
} }
} }
public void sendDiscoverRequest(LwM2mClient lwM2MClient, String targetId, Long timeout) { @Override
String objectId = fromVersionedIdToObjectId(targetId); public void sendExecuteRequest(LwM2mClient client, String targetId, Long timeout, DownlinkRequestCallback callback) {
if (objectId != null && lwM2MClient.isValidObjectVersion(targetId)) { sendExecuteRequest(client, targetId, null, timeout, callback);
sendRequest(lwM2MClient, new DiscoverRequest(objectId), timeout); }
@Override
public void sendExecuteRequest(LwM2mClient client, String targetId, Object params, Long timeout, DownlinkRequestCallback callback) {
String target = fromVersionedIdToObjectId(targetId);
LwM2mPath resultIds = new LwM2mPath(target);
ResourceModel resourceModelExecute = client.getResourceModel(targetId, this.config.getModelProvider());
if (resourceModelExecute != null) {
ExecuteRequest request;
if (params != null && !resourceModelExecute.multiple) {
request = new ExecuteRequest(target, (String) this.converter.convertValue(params, resourceModelExecute.type, ResourceModel.Type.STRING, resultIds));
} else {
request = new ExecuteRequest(target);
}
sendRequest(client, request, timeout);
} }
} }
public void sendWriteAttributesRequest(LwM2mClient lwM2MClient, String targetId, ObjectAttributes params, Long timeout) { public void sendDeleteRequest(LwM2mClient client, String targetId, Long timeout, DownlinkRequestCallback callback) {
String target = fromVersionedIdToObjectId(targetId);
sendRequest(client, new DeleteRequest(target), timeout);
}
@Override
public void sendCancelObserveRequest(LwM2mClient client, String targetId, Long timeout, DownlinkRequestCallback callback) {
int observeCancelCnt = context.getServer().getObservationService().cancelObservations(client.getRegistration(), fromVersionedIdToObjectId(targetId));
String observeCancelMsg = String.format("%s: type operation %s paths: %s count: %d", LOG_LW2M_INFO, OBSERVE_CANCEL.name(), targetId, observeCancelCnt);
if (callback != null) {
callback.onSuccess(client, observeCancelMsg);
}
}
@Override
public void sendCancelAllRequest(LwM2mClient client, Long timeout, DownlinkRequestCallback callback) {
int observeCancelCnt = context.getServer().getObservationService().cancelObservations(client.getRegistration());
String observeCancelMsg = String.format("%s: type operation %s paths: All count: %d", LOG_LW2M_INFO, OBSERVE_CANCEL.name(), observeCancelCnt);
if (callback != null) {
callback.onSuccess(client, observeCancelMsg);
}
}
@Override
public void sendDiscoverRequest(LwM2mClient client, String targetId, Long timeout) {
String objectId = fromVersionedIdToObjectId(targetId); String objectId = fromVersionedIdToObjectId(targetId);
if (objectId != null && lwM2MClient.isValidObjectVersion(targetId) && params != null) { if (objectId != null && client.isValidObjectVersion(targetId)) {
sendRequest(client, new DiscoverRequest(objectId), timeout);
}
}
@Override
public void sendWriteAttributesRequest(LwM2mClient client, String targetId, ObjectAttributes params, Long timeout) {
String objectId = fromVersionedIdToObjectId(targetId);
if (objectId != null && client.isValidObjectVersion(targetId) && params != null) {
List<Attribute> attributes = new LinkedList<>(); List<Attribute> attributes = new LinkedList<>();
// Dimension and Object version are read only attributes. // Dimension and Object version are read only attributes.
// addAttribute(attributes, DIMENSION, params.getDim(), dim -> dim >= 0 && dim <= 255); // addAttribute(attributes, DIMENSION, params.getDim(), dim -> dim >= 0 && dim <= 255);
@ -186,7 +234,55 @@ public class DefaultLwM2mDownlinkMsgHandler implements LwM2mDownlinkMsgHandler {
addAttribute(attributes, LESSER_THAN, params.getLt()); addAttribute(attributes, LESSER_THAN, params.getLt());
addAttribute(attributes, STEP, params.getSt()); addAttribute(attributes, STEP, params.getSt());
AttributeSet attributeSet = new AttributeSet(attributes); AttributeSet attributeSet = new AttributeSet(attributes);
sendRequest(lwM2MClient, new WriteAttributesRequest(objectId, attributeSet), timeout); sendRequest(client, new WriteAttributesRequest(objectId, attributeSet), timeout);
}
}
@Override
public void sendWriteReplaceRequest(LwM2mClient client, String targetIdVer, Object newValue, Long timeout, DownlinkRequestCallback callback) {
ResourceModel resourceModelWrite = client.getResourceModel(targetIdVer, this.config.getModelProvider());
if (resourceModelWrite != null) {
ContentFormat contentFormat = convertResourceModelTypeToContentFormat(client, resourceModelWrite.type);
try {
LwM2mPath path = new LwM2mPath(fromVersionedIdToObjectId(targetIdVer));
WriteRequest request = this.getWriteRequestSingleResource(resourceModelWrite.type, contentFormat,
path.getObjectId(), path.getObjectInstanceId(), path.getResourceId(), newValue);
sendRequest(client, request, timeout);
} catch (Exception e) {
callback.onError(client, e.getMessage(), e);
}
}
}
@Override
public void sendWriteUpdateRequest(LwM2mClient client, String targetIdVer, Object newValue, ContentFormat contentFormat, Long timeout, DownlinkRequestCallback callback) {
LwM2mPath resultIds = new LwM2mPath(fromVersionedIdToObjectId(targetIdVer));
if (resultIds.isResource()) {
/*
* send request: path = '/3/0' node == wM2mObjectInstance
* with params == "\"resources\": {15: resource:{id:15. value:'+01'...}}
**/
Collection<LwM2mResource> resources = client.getNewResourceForInstance(targetIdVer, newValue, this.config.getModelProvider(), this.converter);
ResourceModel resourceModelWrite = client.getResourceModel(targetIdVer, this.config.getModelProvider());
WriteRequest request = new WriteRequest(WriteRequest.Mode.UPDATE, convertResourceModelTypeToContentFormat(client, resourceModelWrite.type), resultIds.getObjectId(),
resultIds.getObjectInstanceId(), resources);
sendRequest(client, request, timeout);
} else if (resultIds.isObjectInstance()) {
/*
* params = "{\"id\":0,\"resources\":[{\"id\":14,\"value\":\"+5\"},{\"id\":15,\"value\":\"+9\"}]}"
* int rscId = resultIds.getObjectInstanceId();
* contentFormat Format of the payload (TLV or JSON).
*/
Collection<LwM2mResource> resources = client.getNewResourcesForInstance(targetIdVer, newValue, this.config.getModelProvider(), this.converter);
if (resources.size() > 0) {
contentFormat = contentFormat.equals(ContentFormat.JSON) ? contentFormat : client.getDefaultContentFormat();
WriteRequest request = new WriteRequest(WriteRequest.Mode.UPDATE, contentFormat, resultIds.getObjectId(), resultIds.getObjectInstanceId(), resources);
sendRequest(client, request, timeout);
} else {
callback.onError(client, "No resources to update!", new IllegalArgumentException());
}
} else {
callback.onError(client, "Update of the root level object is not supported yet", new IllegalArgumentException());
} }
} }
@ -204,32 +300,49 @@ public class DefaultLwM2mDownlinkMsgHandler implements LwM2mDownlinkMsgHandler {
} }
} }
public void sendAllRequest(LwM2mClient lwM2MClient, String targetIdVer, LwM2mTypeOper typeOper, Object params, long timeoutInMs, LwM2mClientRpcRequest lwm2mClientRpcRequest) { private static ContentFormat convertResourceModelTypeToContentFormat(LwM2mClient client, ResourceModel.Type type) {
sendAllRequest(lwM2MClient, targetIdVer, typeOper, lwM2MClient.getDefaultContentFormat(), params, timeoutInMs, lwm2mClientRpcRequest); switch (type) {
case BOOLEAN:
case STRING:
case TIME:
case INTEGER:
case FLOAT:
return client.getDefaultContentFormat();
case OPAQUE:
return ContentFormat.OPAQUE;
case OBJLNK:
return ContentFormat.LINK;
default:
}
throw new CodecException("Invalid ResourceModel_Type for %s ContentFormat.", type);
} }
public void sendAllRequest(LwM2mClient lwM2MClient, String targetIdVer, LwM2mTypeOper typeOper, public void sendAllRequest(LwM2mClient client, String targetIdVer, LwM2mTypeOper typeOper, Object params, long timeoutInMs, LwM2mClientRpcRequest lwm2mClientRpcRequest) {
sendAllRequest(client, targetIdVer, typeOper, client.getDefaultContentFormat(), params, timeoutInMs, lwm2mClientRpcRequest);
}
public void sendAllRequest(LwM2mClient client, String targetIdVer, LwM2mTypeOper typeOper,
ContentFormat contentFormat, Object params, long timeoutInMs, LwM2mClientRpcRequest lwm2mClientRpcRequest) { ContentFormat contentFormat, Object params, long timeoutInMs, LwM2mClientRpcRequest lwm2mClientRpcRequest) {
Registration registration = lwM2MClient.getRegistration(); Registration registration = client.getRegistration();
try { try {
String target = fromVersionedIdToObjectId(targetIdVer); String target = fromVersionedIdToObjectId(targetIdVer);
if (contentFormat == null) { if (contentFormat == null) {
contentFormat = ContentFormat.DEFAULT; contentFormat = client.getDefaultContentFormat();
} }
LwM2mPath resultIds = target != null ? new LwM2mPath(target) : null; LwM2mPath resultIds = target != null ? new LwM2mPath(target) : null;
if (!OBSERVE_CANCEL.name().equals(typeOper.name()) && resultIds != null && registration != null && resultIds.getObjectId() >= 0) { if (!OBSERVE_CANCEL.name().equals(typeOper.name()) && resultIds != null && registration != null && resultIds.getObjectId() >= 0) {
if (lwM2MClient.isValidObjectVersion(targetIdVer)) { if (client.isValidObjectVersion(targetIdVer)) {
timeoutInMs = timeoutInMs > 0 ? timeoutInMs : DEFAULT_TIMEOUT; timeoutInMs = timeoutInMs > 0 ? timeoutInMs : DEFAULT_TIMEOUT;
SimpleDownlinkRequest request = createRequest(registration, lwM2MClient, typeOper, contentFormat, target, SimpleDownlinkRequest request = createRequest(registration, client, typeOper, contentFormat, target,
targetIdVer, resultIds, params, lwm2mClientRpcRequest); targetIdVer, resultIds, params, lwm2mClientRpcRequest);
if (request != null) { if (request != null) {
try { try {
this.sendRequest(lwM2MClient, request, timeoutInMs, lwm2mClientRpcRequest); this.sendRequest(client, request, timeoutInMs, lwm2mClientRpcRequest);
} catch (ClientSleepingException e) { } catch (ClientSleepingException e) {
SimpleDownlinkRequest finalRequest = request; SimpleDownlinkRequest finalRequest = request;
long finalTimeoutInMs = timeoutInMs; long finalTimeoutInMs = timeoutInMs;
LwM2mClientRpcRequest finalRpcRequest = lwm2mClientRpcRequest; LwM2mClientRpcRequest finalRpcRequest = lwm2mClientRpcRequest;
lwM2MClient.getQueuedRequests().add(() -> sendRequest(lwM2MClient, finalRequest, finalTimeoutInMs, finalRpcRequest)); client.getQueuedRequests().add(() -> sendRequest(client, 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);
} }
@ -246,7 +359,7 @@ public class DefaultLwM2mDownlinkMsgHandler implements LwM2mDownlinkMsgHandler {
} 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 (lwm2mClientRpcRequest != null) { if (lwm2mClientRpcRequest != null) {
ResourceModel resourceModel = lwM2MClient.getResourceModel(targetIdVer, this.config.getModelProvider()); ResourceModel resourceModel = client.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.sentRpcResponse(lwm2mClientRpcRequest, NOT_FOUND.getName(), errorMsg, LOG_LW2M_ERROR); handler.sentRpcResponse(lwm2mClientRpcRequest, NOT_FOUND.getName(), errorMsg, LOG_LW2M_ERROR);
} }
@ -270,7 +383,7 @@ public class DefaultLwM2mDownlinkMsgHandler implements LwM2mDownlinkMsgHandler {
} }
String msg = String.format("%s: type operation %s paths - %s", LOG_LW2M_INFO, String msg = String.format("%s: type operation %s paths - %s", LOG_LW2M_INFO,
typeOper.name(), paths); typeOper.name(), paths);
this.handler.sendLogsToThingsboard(lwM2MClient, msg); this.handler.sendLogsToThingsboard(client, msg);
if (lwm2mClientRpcRequest != null) { if (lwm2mClientRpcRequest != null) {
String valueMsg = String.format("Paths - %s", paths); String valueMsg = String.format("Paths - %s", paths);
handler.sentRpcResponse(lwm2mClientRpcRequest, CONTENT.name(), valueMsg, LOG_LW2M_VALUE); handler.sentRpcResponse(lwm2mClientRpcRequest, CONTENT.name(), valueMsg, LOG_LW2M_VALUE);
@ -289,18 +402,18 @@ public class DefaultLwM2mDownlinkMsgHandler implements LwM2mDownlinkMsgHandler {
observeCancelMsg = String.format("%s: type operation %s paths: All count: %d", LOG_LW2M_INFO, observeCancelMsg = String.format("%s: type operation %s paths: All count: %d", LOG_LW2M_INFO,
OBSERVE_CANCEL.name(), observeCancelCnt); OBSERVE_CANCEL.name(), observeCancelCnt);
} }
this.afterObserveCancel(lwM2MClient, observeCancelCnt, observeCancelMsg, lwm2mClientRpcRequest); this.afterObserveCancel(client, observeCancelCnt, observeCancelMsg, lwm2mClientRpcRequest);
break; break;
// lwm2mClientRpcRequest != null // lwm2mClientRpcRequest != null
case FW_UPDATE: case FW_UPDATE:
handler.getInfoFirmwareUpdate(lwM2MClient, lwm2mClientRpcRequest); handler.getInfoFirmwareUpdate(client, lwm2mClientRpcRequest);
break; break;
} }
} }
} 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(lwM2MClient, msg); handler.sendLogsToThingsboard(client, msg);
if (lwm2mClientRpcRequest != 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.sentRpcResponse(lwm2mClientRpcRequest, NOT_FOUND.getName(), errorMsg, LOG_LW2M_ERROR); handler.sentRpcResponse(lwm2mClientRpcRequest, NOT_FOUND.getName(), errorMsg, LOG_LW2M_ERROR);
@ -308,7 +421,7 @@ public class DefaultLwM2mDownlinkMsgHandler implements LwM2mDownlinkMsgHandler {
} }
} }
private SimpleDownlinkRequest createRequest(Registration registration, LwM2mClient lwM2MClient, LwM2mTypeOper typeOper, private SimpleDownlinkRequest createRequest(Registration registration, LwM2mClient client, 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) {
SimpleDownlinkRequest request = null; SimpleDownlinkRequest request = null;
@ -337,7 +450,7 @@ public class DefaultLwM2mDownlinkMsgHandler implements LwM2mDownlinkMsgHandler {
} }
break; break;
case EXECUTE: case EXECUTE:
ResourceModel resourceModelExecute = lwM2MClient.getResourceModel(targetIdVer, this.config.getModelProvider()); ResourceModel resourceModelExecute = client.getResourceModel(targetIdVer, this.config.getModelProvider());
if (resourceModelExecute != null) { if (resourceModelExecute != null) {
if (params != null && !resourceModelExecute.multiple) { if (params != null && !resourceModelExecute.multiple) {
request = new ExecuteRequest(target, (String) this.converter.convertValue(params, resourceModelExecute.type, ResourceModel.Type.STRING, resultIds)); request = new ExecuteRequest(target, (String) this.converter.convertValue(params, resourceModelExecute.type, ResourceModel.Type.STRING, resultIds));
@ -353,12 +466,12 @@ public class DefaultLwM2mDownlinkMsgHandler implements LwM2mDownlinkMsgHandler {
* contentFormat -> TLV, TLV, TLV, TLV, OPAQUE, TLV, LINK * contentFormat -> TLV, TLV, TLV, TLV, OPAQUE, TLV, LINK
* JSON, TEXT; * JSON, TEXT;
**/ **/
ResourceModel resourceModelWrite = lwM2MClient.getResourceModel(targetIdVer, this.config.getModelProvider()); ResourceModel resourceModelWrite = client.getResourceModel(targetIdVer, this.config.getModelProvider());
if (resourceModelWrite != null) { if (resourceModelWrite != null) {
contentFormat = getContentFormatByResourceModelType(resourceModelWrite, contentFormat); // contentFormat = getContentFormatByResourceModelType(resourceModelWrite, contentFormat);
request = this.getWriteRequestSingleResource(contentFormat, resultIds.getObjectId(), // request = this.getWriteRequestSingleResource(contentFormat, resultIds.getObjectId(),
resultIds.getObjectInstanceId(), resultIds.getResourceId(), params, resourceModelWrite.type, // resultIds.getObjectInstanceId(), resultIds.getResourceId(), params, resourceModelWrite.type,
lwM2MClient, rpcRequest); // client, rpcRequest);
} }
break; break;
case WRITE_UPDATE: case WRITE_UPDATE:
@ -367,14 +480,14 @@ public class DefaultLwM2mDownlinkMsgHandler implements LwM2mDownlinkMsgHandler {
* send request: path = '/3/0' node == wM2mObjectInstance * send request: path = '/3/0' node == wM2mObjectInstance
* with params == "\"resources\": {15: resource:{id:15. value:'+01'...}} * with params == "\"resources\": {15: resource:{id:15. value:'+01'...}}
**/ **/
Collection<LwM2mResource> resources = lwM2MClient.getNewResourceForInstance( Collection<LwM2mResource> resources = client.getNewResourceForInstance(
targetIdVer, params, targetIdVer, params,
this.config.getModelProvider(), this.config.getModelProvider(),
this.converter); this.converter);
contentFormat = getContentFormatByResourceModelType(lwM2MClient.getResourceModel(targetIdVer, this.config.getModelProvider()), // contentFormat = getContentFormatByResourceModelType(client.getResourceModel(targetIdVer, this.config.getModelProvider()),
contentFormat); // contentFormat);
request = new WriteRequest(WriteRequest.Mode.UPDATE, contentFormat, resultIds.getObjectId(), // request = new WriteRequest(WriteRequest.Mode.UPDATE, contentFormat, resultIds.getObjectId(),
resultIds.getObjectInstanceId(), resources); // resultIds.getObjectInstanceId(), resources);
} }
/** /**
* params = "{\"id\":0,\"resources\":[{\"id\":14,\"value\":\"+5\"},{\"id\":15,\"value\":\"+9\"}]}" * params = "{\"id\":0,\"resources\":[{\"id\":14,\"value\":\"+5\"},{\"id\":15,\"value\":\"+9\"}]}"
@ -383,7 +496,7 @@ public class DefaultLwM2mDownlinkMsgHandler implements LwM2mDownlinkMsgHandler {
*/ */
else if (resultIds.isObjectInstance()) { else if (resultIds.isObjectInstance()) {
if (((ConcurrentHashMap) params).size() > 0) { if (((ConcurrentHashMap) params).size() > 0) {
Collection<LwM2mResource> resources = lwM2MClient.getNewResourcesForInstance( Collection<LwM2mResource> resources = client.getNewResourcesForInstance(
targetIdVer, params, targetIdVer, params,
this.config.getModelProvider(), this.config.getModelProvider(),
this.converter); this.converter);
@ -407,33 +520,33 @@ public class DefaultLwM2mDownlinkMsgHandler implements LwM2mDownlinkMsgHandler {
return request; return request;
} }
private void sendRequest(LwM2mClient lwM2MClient, SimpleDownlinkRequest request, long timeoutInMs) { private void sendRequest(LwM2mClient client, SimpleDownlinkRequest request, long timeoutInMs) {
try { try {
sendRequest(lwM2MClient, request, timeoutInMs, null); sendRequest(client, request, timeoutInMs, null);
} catch (ClientSleepingException e) { } catch (ClientSleepingException e) {
//TODO: this may cause infinite loop / memory leak. //TODO: this may cause infinite loop / memory leak.
lwM2MClient.getQueuedRequests().add(() -> sendRequest(lwM2MClient, request, timeoutInMs, null)); client.getQueuedRequests().add(() -> sendRequest(client, request, timeoutInMs, null));
} }
} }
@SuppressWarnings({"error sendRequest"}) @SuppressWarnings({"error sendRequest"})
private void sendRequest(LwM2mClient lwM2MClient, SimpleDownlinkRequest request, long timeoutInMs, LwM2mClientRpcRequest rpcRequest) { private void sendRequest(LwM2mClient client, SimpleDownlinkRequest request, long timeoutInMs, LwM2mClientRpcRequest rpcRequest) {
Registration registration = lwM2MClient.getRegistration(); Registration registration = client.getRegistration();
context.getServer().send(registration, request, timeoutInMs, (ResponseCallback<?>) response -> { context.getServer().send(registration, request, timeoutInMs, (ResponseCallback<?>) response -> {
if (!lwM2MClient.isInit()) { if (!client.isInit()) {
lwM2MClient.initReadValue(this.handler, convertPathFromObjectIdToIdVer(request.getPath().toString(), registration)); client.initReadValue(this.handler, convertPathFromObjectIdToIdVer(request.getPath().toString(), registration));
} }
if (CoAP.ResponseCode.isSuccess(((Response) response.getCoapResponse()).getCode())) { if (CoAP.ResponseCode.isSuccess(((Response) response.getCoapResponse()).getCode())) {
this.handleResponse(lwM2MClient, request.getPath().toString(), response, request, rpcRequest); this.handleResponse(client, request.getPath().toString(), response, request, rpcRequest);
} else { } else {
String msg = String.format("%s: SendRequest %s: CoapCode - %s Lwm2m code - %d name - %s Resource path - %s", LOG_LW2M_ERROR, request.getClass().getName().toString(), String msg = String.format("%s: SendRequest %s: CoapCode - %s Lwm2m code - %d name - %s Resource path - %s", LOG_LW2M_ERROR, request.getClass().getName().toString(),
((Response) response.getCoapResponse()).getCode(), response.getCode().getCode(), response.getCode().getName(), request.getPath().toString()); ((Response) response.getCoapResponse()).getCode(), response.getCode().getCode(), response.getCode().getName(), request.getPath().toString());
handler.sendLogsToThingsboard(lwM2MClient, msg); handler.sendLogsToThingsboard(client, msg);
log.error("[{}] [{}], [{}] - [{}] [{}] error SendRequest", request.getClass().getName().toString(), registration.getEndpoint(), log.error("[{}] [{}], [{}] - [{}] [{}] error SendRequest", request.getClass().getName().toString(), registration.getEndpoint(),
((Response) response.getCoapResponse()).getCode(), response.getCode(), request.getPath().toString()); ((Response) response.getCoapResponse()).getCode(), response.getCode(), request.getPath().toString());
if (!lwM2MClient.isInit()) { if (!client.isInit()) {
lwM2MClient.initReadValue(this.handler, convertPathFromObjectIdToIdVer(request.getPath().toString(), registration)); client.initReadValue(this.handler, convertPathFromObjectIdToIdVer(request.getPath().toString(), registration));
} }
/** Not Found */ /** Not Found */
if (rpcRequest != null) { if (rpcRequest != null) {
@ -442,11 +555,11 @@ public class DefaultLwM2mDownlinkMsgHandler implements LwM2mDownlinkMsgHandler {
/** Not Found /** Not Found
set setClient_fw_info... = empty set setClient_fw_info... = empty
**/ **/
if (lwM2MClient.getFwUpdate() != null && lwM2MClient.getFwUpdate().isInfoFwSwUpdate()) { if (client.getFwUpdate() != null && client.getFwUpdate().isInfoFwSwUpdate()) {
lwM2MClient.getFwUpdate().initReadValue(handler, this, request.getPath().toString()); client.getFwUpdate().initReadValue(handler, this, request.getPath().toString());
} }
if (lwM2MClient.getSwUpdate() != null && lwM2MClient.getSwUpdate().isInfoFwSwUpdate()) { if (client.getSwUpdate() != null && client.getSwUpdate().isInfoFwSwUpdate()) {
lwM2MClient.getSwUpdate().initReadValue(handler, this, request.getPath().toString()); client.getSwUpdate().initReadValue(handler, this, request.getPath().toString());
} }
if (request.getPath().toString().equals(FW_PACKAGE_5_ID) || request.getPath().toString().equals(SW_PACKAGE_ID)) { if (request.getPath().toString().equals(FW_PACKAGE_5_ID) || request.getPath().toString().equals(SW_PACKAGE_ID)) {
this.afterWriteFwSWUpdateError(registration, request, response.getErrorMessage()); this.afterWriteFwSWUpdateError(registration, request, response.getErrorMessage());
@ -459,11 +572,11 @@ public class DefaultLwM2mDownlinkMsgHandler implements LwM2mDownlinkMsgHandler {
/** version == null /** version == null
set setClient_fw_info... = empty set setClient_fw_info... = empty
**/ **/
if (lwM2MClient.getFwUpdate() != null && lwM2MClient.getFwUpdate().isInfoFwSwUpdate()) { if (client.getFwUpdate() != null && client.getFwUpdate().isInfoFwSwUpdate()) {
lwM2MClient.getFwUpdate().initReadValue(handler, this, request.getPath().toString()); client.getFwUpdate().initReadValue(handler, this, request.getPath().toString());
} }
if (lwM2MClient.getSwUpdate() != null && lwM2MClient.getSwUpdate().isInfoFwSwUpdate()) { if (client.getSwUpdate() != null && client.getSwUpdate().isInfoFwSwUpdate()) {
lwM2MClient.getSwUpdate().initReadValue(handler, this, request.getPath().toString()); client.getSwUpdate().initReadValue(handler, this, request.getPath().toString());
} }
if (request.getPath().toString().equals(FW_PACKAGE_5_ID) || request.getPath().toString().equals(SW_PACKAGE_ID)) { if (request.getPath().toString().equals(FW_PACKAGE_5_ID) || request.getPath().toString().equals(SW_PACKAGE_ID)) {
this.afterWriteFwSWUpdateError(registration, request, e.getMessage()); this.afterWriteFwSWUpdateError(registration, request, e.getMessage());
@ -471,12 +584,12 @@ public class DefaultLwM2mDownlinkMsgHandler implements LwM2mDownlinkMsgHandler {
if (request.getPath().toString().equals(FW_UPDATE_ID) || request.getPath().toString().equals(SW_INSTALL_ID)) { if (request.getPath().toString().equals(FW_UPDATE_ID) || request.getPath().toString().equals(SW_INSTALL_ID)) {
this.afterExecuteFwSwUpdateError(registration, request, e.getMessage()); this.afterExecuteFwSwUpdateError(registration, request, e.getMessage());
} }
if (!lwM2MClient.isInit()) { if (!client.isInit()) {
lwM2MClient.initReadValue(this.handler, convertPathFromObjectIdToIdVer(request.getPath().toString(), registration)); client.initReadValue(this.handler, convertPathFromObjectIdToIdVer(request.getPath().toString(), registration));
} }
String msg = String.format("%s: SendRequest %s: Resource path - %s msg error - %s", String msg = String.format("%s: SendRequest %s: Resource path - %s msg error - %s",
LOG_LW2M_ERROR, request.getClass().getName().toString(), request.getPath().toString(), e.getMessage()); LOG_LW2M_ERROR, request.getClass().getName().toString(), request.getPath().toString(), e.getMessage());
handler.sendLogsToThingsboard(lwM2MClient, msg); handler.sendLogsToThingsboard(client, msg);
log.error("[{}] [{}] - [{}] error SendRequest", request.getClass().getName().toString(), request.getPath().toString(), e.toString()); log.error("[{}] [{}] - [{}] error SendRequest", request.getClass().getName().toString(), request.getPath().toString(), e.toString());
if (rpcRequest != null) { if (rpcRequest != null) {
handler.sentRpcResponse(rpcRequest, CoAP.CodeClass.ERROR_RESPONSE.name(), e.getMessage(), LOG_LW2M_ERROR); handler.sentRpcResponse(rpcRequest, CoAP.CodeClass.ERROR_RESPONSE.name(), e.getMessage(), LOG_LW2M_ERROR);
@ -484,51 +597,51 @@ public class DefaultLwM2mDownlinkMsgHandler implements LwM2mDownlinkMsgHandler {
}); });
} }
private WriteRequest getWriteRequestSingleResource(ContentFormat contentFormat, Integer objectId, Integer instanceId, private WriteRequest getWriteRequestSingleResource(ResourceModel.Type type, ContentFormat contentFormat, int objectId, int instanceId, int resourceId, Object value) {
Integer resourceId, Object value, ResourceModel.Type type, switch (type) {
LwM2mClient client, LwM2mClientRpcRequest rpcRequest) { case STRING: // String
try { return new WriteRequest(contentFormat, objectId, instanceId, resourceId, value.toString());
if (type != null) { case INTEGER: // Long
switch (type) { final long valueInt = Integer.toUnsignedLong(Integer.parseInt(value.toString()));
case STRING: // String return new WriteRequest(contentFormat, objectId, instanceId, resourceId, valueInt);
return (contentFormat == null) ? new WriteRequest(objectId, instanceId, resourceId, value.toString()) : new WriteRequest(contentFormat, objectId, instanceId, resourceId, value.toString()); case OBJLNK: // ObjectLink
case INTEGER: // Long return new WriteRequest(contentFormat, objectId, instanceId, resourceId, ObjectLink.fromPath(value.toString()));
final long valueInt = Integer.toUnsignedLong(Integer.parseInt(value.toString())); case BOOLEAN: // Boolean
return (contentFormat == null) ? new WriteRequest(objectId, instanceId, resourceId, valueInt) : new WriteRequest(contentFormat, objectId, instanceId, resourceId, valueInt); return new WriteRequest(contentFormat, objectId, instanceId, resourceId, Boolean.parseBoolean(value.toString()));
case OBJLNK: // ObjectLink case FLOAT: // Double
return (contentFormat == null) ? new WriteRequest(objectId, instanceId, resourceId, ObjectLink.fromPath(value.toString())) : new WriteRequest(contentFormat, objectId, instanceId, resourceId, ObjectLink.fromPath(value.toString())); return new WriteRequest(contentFormat, objectId, instanceId, resourceId, Double.parseDouble(value.toString()));
case BOOLEAN: // Boolean case TIME: // Date
return (contentFormat == null) ? new WriteRequest(objectId, instanceId, resourceId, Boolean.parseBoolean(value.toString())) : new WriteRequest(contentFormat, objectId, instanceId, resourceId, Boolean.parseBoolean(value.toString())); Date date = new Date(Long.decode(value.toString()));
case FLOAT: // Double return new WriteRequest(contentFormat, objectId, instanceId, resourceId, date);
return (contentFormat == null) ? new WriteRequest(objectId, instanceId, resourceId, Double.parseDouble(value.toString())) : new WriteRequest(contentFormat, objectId, instanceId, resourceId, Double.parseDouble(value.toString())); case OPAQUE: // byte[] value, base64
case TIME: // Date byte[] valueRequest;
Date date = new Date(Long.decode(value.toString())); if (value instanceof byte[]) {
return (contentFormat == null) ? new WriteRequest(objectId, instanceId, resourceId, date) : new WriteRequest(contentFormat, objectId, instanceId, resourceId, date); valueRequest = (byte[]) value;
case OPAQUE: // byte[] value, base64 } else {
byte[] valueRequest = value instanceof byte[] ? (byte[]) value : Hex.decodeHex(value.toString().toCharArray()); valueRequest = Hex.decodeHex(value.toString().toCharArray());
return (contentFormat == null) ? new WriteRequest(objectId, instanceId, resourceId, valueRequest) :
new WriteRequest(contentFormat, objectId, instanceId, resourceId, valueRequest);
default:
} }
} return new WriteRequest(contentFormat, objectId, instanceId, resourceId, valueRequest);
if (rpcRequest != null) { default:
String patn = "/" + objectId + "/" + instanceId + "/" + resourceId;
String errorMsg = String.format("Bad ResourceModel Operations (E): Resource path - %s ResourceModel type - %s", patn, type);
rpcRequest.setErrorMsg(errorMsg);
}
return null;
} catch (NumberFormatException e) {
String patn = "/" + objectId + "/" + instanceId + "/" + resourceId;
String msg = String.format(LOG_LW2M_ERROR + ": NumberFormatException: Resource path - %s type - %s value - %s msg error - %s SendRequest to Client",
patn, type, value, e.toString());
handler.sendLogsToThingsboard(client, msg);
log.error("Path: [{}] type: [{}] value: [{}] errorMsg: [{}]]", patn, type, value, e.toString());
if (rpcRequest != null) {
String errorMsg = String.format("NumberFormatException: Resource path - %s type - %s value - %s", patn, type, value);
handler.sentRpcResponse(rpcRequest, BAD_REQUEST.getName(), errorMsg, LOG_LW2M_ERROR);
}
return null;
} }
// TODO: throw exception and execute callback.
//// if (rpcRequest != null) {
//// String patn = "/" + objectId + "/" + instanceId + "/" + resourceId;
//// String errorMsg = String.format("Bad ResourceModel Operations (E): Resource path - %s ResourceModel type - %s", patn, type);
//// rpcRequest.setErrorMsg(errorMsg);
//// }
// return null;
// } catch (NumberFormatException e) {
// String patn = "/" + objectId + "/" + instanceId + "/" + resourceId;
// String msg = String.format(LOG_LW2M_ERROR + ": NumberFormatException: Resource path - %s type - %s value - %s msg error - %s SendRequest to Client",
// patn, type, value, e.toString());
// handler.sendLogsToThingsboard(client, msg);
// log.error("Path: [{}] type: [{}] value: [{}] errorMsg: [{}]]", patn, type, value, e.toString());
// if (rpcRequest != null) {
// String errorMsg = String.format("NumberFormatException: Resource path - %s type - %s value - %s", patn, type, value);
// handler.sentRpcResponse(rpcRequest, BAD_REQUEST.getName(), errorMsg, LOG_LW2M_ERROR);
// }
// return null;
// }
} }
private void handleResponse(LwM2mClient lwM2mClient, final String path, LwM2mResponse response, private void handleResponse(LwM2mClient lwM2mClient, final String path, LwM2mResponse response,
@ -597,7 +710,8 @@ public class DefaultLwM2mDownlinkMsgHandler implements LwM2mDownlinkMsgHandler {
} }
} }
private void infoWriteResponse(LwM2mClient lwM2mClient, LwM2mResponse response, SimpleDownlinkRequest request, LwM2mClientRpcRequest rpcRequest) { private void infoWriteResponse(LwM2mClient lwM2mClient, LwM2mResponse response, SimpleDownlinkRequest
request, LwM2mClientRpcRequest rpcRequest) {
try { try {
Registration registration = lwM2mClient.getRegistration(); Registration registration = lwM2mClient.getRegistration();
LwM2mNode node = ((WriteRequest) request).getNode(); LwM2mNode node = ((WriteRequest) request).getNode();
@ -655,43 +769,46 @@ public class DefaultLwM2mDownlinkMsgHandler implements LwM2mDownlinkMsgHandler {
* send operation Execute * send operation Execute
*/ */
private void afterWriteSuccessFwSwUpdate(Registration registration, SimpleDownlinkRequest request) { private void afterWriteSuccessFwSwUpdate(Registration registration, SimpleDownlinkRequest request) {
LwM2mClient lwM2MClient = this.lwM2mClientContext.getClientByRegistrationId(registration.getId()); LwM2mClient client = this.lwM2mClientContext.getClientByRegistrationId(registration.getId());
if (request.getPath().toString().equals(FW_PACKAGE_5_ID) && lwM2MClient.getFwUpdate() != null) { if (request.getPath().toString().equals(FW_PACKAGE_5_ID) && client.getFwUpdate() != null) {
lwM2MClient.getFwUpdate().setStateUpdate(DOWNLOADED.name()); client.getFwUpdate().setStateUpdate(DOWNLOADED.name());
lwM2MClient.getFwUpdate().sendLogs(this.handler, WRITE_REPLACE.name(), LOG_LW2M_INFO, null); client.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) && client.getSwUpdate() != null) {
lwM2MClient.getSwUpdate().setStateUpdate(DOWNLOADED.name()); client.getSwUpdate().setStateUpdate(DOWNLOADED.name());
lwM2MClient.getSwUpdate().sendLogs(this.handler, WRITE_REPLACE.name(), LOG_LW2M_INFO, null); client.getSwUpdate().sendLogs(this.handler, WRITE_REPLACE.name(), LOG_LW2M_INFO, null);
} }
} }
/** /**
* After finish operation FwSwUpdate Write (error): fw_state = FAILED * After finish operation FwSwUpdate Write (error): fw_state = FAILED
*/ */
private void afterWriteFwSWUpdateError(Registration registration, SimpleDownlinkRequest request, String msgError) { private void afterWriteFwSWUpdateError(Registration registration, SimpleDownlinkRequest request, String
LwM2mClient lwM2MClient = this.lwM2mClientContext.getClientByRegistrationId(registration.getId()); msgError) {
if (request.getPath().toString().equals(FW_PACKAGE_5_ID) && lwM2MClient.getFwUpdate() != null) { LwM2mClient client = this.lwM2mClientContext.getClientByRegistrationId(registration.getId());
lwM2MClient.getFwUpdate().setStateUpdate(FAILED.name()); if (request.getPath().toString().equals(FW_PACKAGE_5_ID) && client.getFwUpdate() != null) {
lwM2MClient.getFwUpdate().sendLogs(this.handler, WRITE_REPLACE.name(), LOG_LW2M_ERROR, msgError); client.getFwUpdate().setStateUpdate(FAILED.name());
client.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) && client.getSwUpdate() != null) {
lwM2MClient.getSwUpdate().setStateUpdate(FAILED.name()); client.getSwUpdate().setStateUpdate(FAILED.name());
lwM2MClient.getSwUpdate().sendLogs(this.handler, WRITE_REPLACE.name(), LOG_LW2M_ERROR, msgError); client.getSwUpdate().sendLogs(this.handler, WRITE_REPLACE.name(), LOG_LW2M_ERROR, msgError);
} }
} }
private void afterExecuteFwSwUpdateError(Registration registration, SimpleDownlinkRequest request, String msgError) { private void afterExecuteFwSwUpdateError(Registration registration, SimpleDownlinkRequest request, String
LwM2mClient lwM2MClient = this.lwM2mClientContext.getClientByRegistrationId(registration.getId()); msgError) {
if (request.getPath().toString().equals(FW_UPDATE_ID) && lwM2MClient.getFwUpdate() != null) { LwM2mClient client = this.lwM2mClientContext.getClientByRegistrationId(registration.getId());
lwM2MClient.getFwUpdate().sendLogs(this.handler, EXECUTE.name(), LOG_LW2M_ERROR, msgError); if (request.getPath().toString().equals(FW_UPDATE_ID) && client.getFwUpdate() != null) {
client.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) && client.getSwUpdate() != null) {
lwM2MClient.getSwUpdate().sendLogs(this.handler, EXECUTE.name(), LOG_LW2M_ERROR, msgError); client.getSwUpdate().sendLogs(this.handler, EXECUTE.name(), LOG_LW2M_ERROR, msgError);
} }
} }
private void afterObserveCancel(LwM2mClient lwM2mClient, int observeCancelCnt, String observeCancelMsg, LwM2mClientRpcRequest rpcRequest) { private void afterObserveCancel(LwM2mClient lwM2mClient, int observeCancelCnt, String
observeCancelMsg, LwM2mClientRpcRequest rpcRequest) {
handler.sendLogsToThingsboard(lwM2mClient, observeCancelMsg); handler.sendLogsToThingsboard(lwM2mClient, observeCancelMsg);
log.warn("[{}]", observeCancelMsg); log.warn("[{}]", observeCancelMsg);
if (rpcRequest != null) { if (rpcRequest != null) {

View File

@ -1,4 +1,48 @@
/**
* 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; package org.thingsboard.server.transport.lwm2m.server;
import org.eclipse.leshan.core.request.ContentFormat;
import org.thingsboard.server.common.data.device.data.lwm2m.ObjectAttributes;
import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
import org.thingsboard.server.transport.lwm2m.server.downlink.DownlinkRequestCallback;
public interface LwM2mDownlinkMsgHandler { public interface LwM2mDownlinkMsgHandler {
void sendReadRequest(LwM2mClient client, String targetId, Long timeout);
void sendReadRequest(LwM2mClient client, String targetId, ContentFormat contentFormat, Long timeout);
void sendObserveRequest(LwM2mClient client, String targetId, Long timeout);
void sendObserveRequest(LwM2mClient client, String targetId, ContentFormat contentFormat, Long timeout);
void sendExecuteRequest(LwM2mClient client, String targetId, Long timeout, DownlinkRequestCallback callback);
void sendExecuteRequest(LwM2mClient client, String targetId, Object params, Long timeout, DownlinkRequestCallback callback);
void sendCancelObserveRequest(LwM2mClient client, String targetId, Long timeout, DownlinkRequestCallback callback);
void sendCancelAllRequest(LwM2mClient client, Long timeout, DownlinkRequestCallback callback);
void sendDiscoverRequest(LwM2mClient client, String targetId, Long timeout);
void sendWriteAttributesRequest(LwM2mClient client, String targetId, ObjectAttributes params, Long timeout);
void sendWriteReplaceRequest(LwM2mClient client, String targetIdVer, Object newValue, Long timeout, DownlinkRequestCallback callback);
void sendWriteUpdateRequest(LwM2mClient client, String targetIdVer, Object newValue, ContentFormat contentFormat, Long timeout, DownlinkRequestCallback callback);
} }

View File

@ -48,6 +48,7 @@ import org.thingsboard.server.gen.transport.TransportProtos.PostTelemetryMsg;
import org.thingsboard.server.gen.transport.TransportProtos.SessionInfoProto; import org.thingsboard.server.gen.transport.TransportProtos.SessionInfoProto;
import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;
import org.thingsboard.server.transport.lwm2m.server.adaptors.LwM2MJsonAdaptor; import org.thingsboard.server.transport.lwm2m.server.adaptors.LwM2MJsonAdaptor;
import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.IOException; import java.io.IOException;
@ -210,28 +211,6 @@ public class LwM2mTransportServerHelper {
throw new CodecException("Invalid ResourceModel_Type for resource %s, got %s", resourcePath, currentType); throw new CodecException("Invalid ResourceModel_Type for resource %s, got %s", resourcePath, currentType);
} }
public static ContentFormat convertResourceModelTypeToContentFormat(ResourceModel.Type type) {
switch (type) {
case BOOLEAN:
case STRING:
case TIME:
case INTEGER:
case FLOAT:
return ContentFormat.TLV;
case OPAQUE:
return ContentFormat.OPAQUE;
case OBJLNK:
return ContentFormat.LINK;
default:
}
throw new CodecException("Invalid ResourceModel_Type for %s ContentFormat.", type);
}
public static ContentFormat getContentFormatByResourceModelType(ResourceModel resourceModel, ContentFormat contentFormat) {
return contentFormat.equals(ContentFormat.TLV) ? convertResourceModelTypeToContentFormat(resourceModel.type) :
contentFormat;
}
public static Object getValueFromKvProto(TransportProtos.KeyValueProto kv) { public static Object getValueFromKvProto(TransportProtos.KeyValueProto kv) {
switch (kv.getType()) { switch (kv.getType()) {
case BOOLEAN_V: case BOOLEAN_V:

View File

@ -302,7 +302,7 @@ public class LwM2mClient implements Cloneable {
Map<Integer, ResourceModel> resourceModels = modelProvider.getObjectModel(registration) Map<Integer, ResourceModel> resourceModels = modelProvider.getObjectModel(registration)
.getObjectModel(pathIds.getObjectId()).resources; .getObjectModel(pathIds.getObjectId()).resources;
resourceModels.forEach((resId, resourceModel) -> { resourceModels.forEach((resId, resourceModel) -> {
if (resId == pathIds.getResourceId()) { if (resId.equals(pathIds.getResourceId())) {
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));
@ -318,8 +318,8 @@ public class LwM2mClient implements Cloneable {
Map<Integer, ResourceModel> resourceModels = modelProvider.getObjectModel(registration) Map<Integer, ResourceModel> resourceModels = modelProvider.getObjectModel(registration)
.getObjectModel(pathIds.getObjectId()).resources; .getObjectModel(pathIds.getObjectId()).resources;
resourceModels.forEach((resId, resourceModel) -> { resourceModels.forEach((resId, resourceModel) -> {
if (((ConcurrentHashMap) params).containsKey(String.valueOf(resId))) { if (((Map) params).containsKey(String.valueOf(resId))) {
Object value = ((ConcurrentHashMap) params).get((String.valueOf(resId))); Object value = ((Map) params).get((String.valueOf(resId)));
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));

View File

@ -25,7 +25,7 @@ import org.thingsboard.server.common.data.ota.OtaPackageType;
import org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus; import org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus;
import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.gen.transport.TransportProtos;
import org.thingsboard.server.transport.lwm2m.server.DefaultLwM2MUplinkMsgHandler; import org.thingsboard.server.transport.lwm2m.server.DefaultLwM2MUplinkMsgHandler;
import org.thingsboard.server.transport.lwm2m.server.DefaultLwM2mDownlinkMsgHandler; import org.thingsboard.server.transport.lwm2m.server.LwM2mDownlinkMsgHandler;
import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil; import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil;
import java.util.ArrayList; import java.util.ArrayList;
@ -156,7 +156,7 @@ public class LwM2mFwSwUpdate {
} }
} }
public void initReadValue(DefaultLwM2MUplinkMsgHandler handler, DefaultLwM2mDownlinkMsgHandler request, String pathIdVer) { public void initReadValue(DefaultLwM2MUplinkMsgHandler handler, LwM2mDownlinkMsgHandler request, String pathIdVer) {
if (pathIdVer != null) { if (pathIdVer != null) {
this.pendingInfoRequestsStart.remove(pathIdVer); this.pendingInfoRequestsStart.remove(pathIdVer);
} }
@ -176,7 +176,7 @@ public class LwM2mFwSwUpdate {
* Send FsSw to Lwm2mClient: * Send FsSw to Lwm2mClient:
* before operation Write: fw_state = DOWNLOADING * before operation Write: fw_state = DOWNLOADING
*/ */
public void writeFwSwWare(DefaultLwM2MUplinkMsgHandler handler, DefaultLwM2mDownlinkMsgHandler request) { public void writeFwSwWare(DefaultLwM2MUplinkMsgHandler handler, LwM2mDownlinkMsgHandler request) {
if (this.currentId != null) { if (this.currentId != null) {
this.stateUpdate = OtaPackageUpdateStatus.INITIATED.name(); this.stateUpdate = OtaPackageUpdateStatus.INITIATED.name();
this.sendLogs(handler, WRITE_REPLACE.name(), LOG_LW2M_INFO, null); this.sendLogs(handler, WRITE_REPLACE.name(), LOG_LW2M_INFO, null);
@ -189,8 +189,7 @@ public class LwM2mFwSwUpdate {
int chunkSize = 0; int chunkSize = 0;
int chunk = 0; int chunk = 0;
byte[] firmwareChunk = handler.otaPackageDataCache.get(this.currentId.toString(), chunkSize, chunk); byte[] firmwareChunk = handler.otaPackageDataCache.get(this.currentId.toString(), chunkSize, chunk);
request.sendAllRequest(this.lwM2MClient, targetIdVer, WRITE_REPLACE, ContentFormat.OPAQUE, request.sendWriteReplaceRequest(this.lwM2MClient, targetIdVer, firmwareChunk, handler.config.getTimeout(), this.rpcRequest);
firmwareChunk, handler.config.getTimeout(), this.rpcRequest);
} else if (LwM2mTransportUtil.LwM2MFirmwareUpdateStrategy.OBJ_5_TEMP_URL.code == this.updateStrategy) { } else if (LwM2mTransportUtil.LwM2MFirmwareUpdateStrategy.OBJ_5_TEMP_URL.code == this.updateStrategy) {
Registration registration = this.getLwM2MClient().getRegistration(); Registration registration = this.getLwM2MClient().getRegistration();
// String api = handler.config.getHostRequests(); // String api = handler.config.getHostRequests();
@ -198,8 +197,7 @@ public class LwM2mFwSwUpdate {
int port = registration.getIdentity().isSecure() ? handler.config.getSecurePort() : handler.config.getPort(); int port = registration.getIdentity().isSecure() ? handler.config.getSecurePort() : handler.config.getPort();
String uri = "coap://" + api + ":" + Integer.valueOf(port) + "/" + FIRMWARE_UPDATE_COAP_RECOURSE + "/" + this.currentId.toString(); String uri = "coap://" + api + ":" + Integer.valueOf(port) + "/" + FIRMWARE_UPDATE_COAP_RECOURSE + "/" + this.currentId.toString();
log.warn("89) coapUri: [{}]", uri); log.warn("89) coapUri: [{}]", uri);
request.sendAllRequest(this.lwM2MClient, targetIdVer, WRITE_REPLACE, null, request.sendWriteReplaceRequest(this.lwM2MClient, targetIdVer, uri, handler.config.getTimeout(), this.rpcRequest);
uri, handler.config.getTimeout(), this.rpcRequest);
} else if (LwM2mTransportUtil.LwM2MFirmwareUpdateStrategy.OBJ_19_BINARY.code == this.updateStrategy) { } else if (LwM2mTransportUtil.LwM2MFirmwareUpdateStrategy.OBJ_19_BINARY.code == this.updateStrategy) {
} }
@ -230,9 +228,9 @@ public class LwM2mFwSwUpdate {
* fw_state/sw_state = UPDATING * fw_state/sw_state = UPDATING
* send execute * send execute
*/ */
public void executeFwSwWare(DefaultLwM2MUplinkMsgHandler handler, DefaultLwM2mDownlinkMsgHandler request) { public void executeFwSwWare(DefaultLwM2MUplinkMsgHandler handler, LwM2mDownlinkMsgHandler request) {
this.sendLogs(handler, EXECUTE.name(), LOG_LW2M_INFO, null); this.sendLogs(handler, EXECUTE.name(), LOG_LW2M_INFO, null);
request.sendAllRequest(this.lwM2MClient, this.pathInstallId, EXECUTE, null, 0, this.rpcRequest); request.sendExecuteRequest(this.lwM2MClient, this.pathInstallId, handler.config.getTimeout(), this.rpcRequest);
} }
/** /**
@ -381,14 +379,14 @@ public class LwM2mFwSwUpdate {
return LwM2mTransportUtil.UpdateResultSw.NOT_ENOUGH_STORAGE.code <= updateResult; return LwM2mTransportUtil.UpdateResultSw.NOT_ENOUGH_STORAGE.code <= updateResult;
} }
private void observeStateUpdate(DefaultLwM2MUplinkMsgHandler handler, DefaultLwM2mDownlinkMsgHandler request) { // private void observeStateUpdate(DefaultLwM2MUplinkMsgHandler handler, LwM2mDownlinkMsgHandler request) {
request.sendAllRequest(lwM2MClient, // request.sendAllRequest(lwM2MClient,
convertPathFromObjectIdToIdVer(this.pathStateId, this.lwM2MClient.getRegistration()), OBSERVE, // convertPathFromObjectIdToIdVer(this.pathStateId, this.lwM2MClient.getRegistration()), OBSERVE,
null, null, 0, null); // null, null, 0, null);
request.sendAllRequest(lwM2MClient, // request.sendAllRequest(lwM2MClient,
convertPathFromObjectIdToIdVer(this.pathResultId, this.lwM2MClient.getRegistration()), OBSERVE, // convertPathFromObjectIdToIdVer(this.pathResultId, this.lwM2MClient.getRegistration()), OBSERVE,
null, null, 0, null); // null, null, 0, null);
} // }
public void sendSateOnThingsBoard(DefaultLwM2MUplinkMsgHandler handler) { public void sendSateOnThingsBoard(DefaultLwM2MUplinkMsgHandler handler) {
if (StringUtils.trimToNull(this.stateUpdate) != null) { if (StringUtils.trimToNull(this.stateUpdate) != null) {
@ -401,7 +399,7 @@ public class LwM2mFwSwUpdate {
} }
} }
public void sendReadObserveInfo(DefaultLwM2mDownlinkMsgHandler request) { public void sendReadObserveInfo(LwM2mDownlinkMsgHandler request) {
this.infoFwSwUpdate = true; this.infoFwSwUpdate = true;
this.pendingInfoRequestsStart.add(convertPathFromObjectIdToIdVer( this.pendingInfoRequestsStart.add(convertPathFromObjectIdToIdVer(
this.pathStateId, this.lwM2MClient.getRegistration())); this.pathStateId, this.lwM2MClient.getRegistration()));
@ -418,7 +416,7 @@ public class LwM2mFwSwUpdate {
this.pathNameId, this.lwM2MClient.getRegistration())); this.pathNameId, this.lwM2MClient.getRegistration()));
} }
this.pendingInfoRequestsStart.forEach(pathIdVer -> { this.pendingInfoRequestsStart.forEach(pathIdVer -> {
request.sendAllRequest(this.lwM2MClient, pathIdVer, OBSERVE, null, 0, this.rpcRequest); request.sendObserveRequest(this.lwM2MClient, pathIdVer, 0, this.rpcRequest);
}); });
} }
@ -433,7 +431,7 @@ public class LwM2mFwSwUpdate {
* - after success finished operation Execute (FwUpdate) Update Result == 1 ("Firmware updated successfully") * - after success finished operation Execute (FwUpdate) Update Result == 1 ("Firmware updated successfully")
* - finished operation Execute (FwUpdate) * - finished operation Execute (FwUpdate)
*/ */
public void updateStateOta(DefaultLwM2MUplinkMsgHandler handler, DefaultLwM2mDownlinkMsgHandler request, public void updateStateOta(DefaultLwM2MUplinkMsgHandler handler, LwM2mDownlinkMsgHandler request,
Registration registration, String path, int value) { Registration registration, String path, int value) {
if (OBJ_5_BINARY.code == this.getUpdateStrategy()) { if (OBJ_5_BINARY.code == this.getUpdateStrategy()) {
if ((convertPathFromObjectIdToIdVer(FW_RESULT_ID, registration).equals(path))) { if ((convertPathFromObjectIdToIdVer(FW_RESULT_ID, registration).equals(path))) {

View File

@ -0,0 +1,25 @@
/**
* Copyright © 2016-2021 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.transport.lwm2m.server.downlink;
import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
public interface DownlinkRequestCallback {
void onSuccess(LwM2mClient client, String msg);
void onError(LwM2mClient client, String msg, Exception e);
}

View File

@ -117,7 +117,7 @@ public class LwM2mValueConverterImpl implements LwM2mValueConverter {
switch (currentType) { switch (currentType) {
case INTEGER: case INTEGER:
log.debug("Trying to convert long value {} to date", value); log.debug("Trying to convert long value {} to date", value);
/** let's assume we received the millisecond since 1970/1/1 */ /* let's assume we received the millisecond since 1970/1/1 */
return new Date(((Number) value).longValue() * 1000L); return new Date(((Number) value).longValue() * 1000L);
case STRING: case STRING:
log.debug("Trying to convert string value {} to date", value); log.debug("Trying to convert string value {} to date", value);