Merge pull request #5775 from YevhenBondarenko/develop/3.3.3-lwm2m-improvements
[3.3.3] lwm2m improvements
This commit is contained in:
		
						commit
						b21e1be0eb
					
				@ -108,24 +108,6 @@ public class RpcLwm2mIntegrationWriteTest extends AbstractRpcLwM2MIntegrationTes
 | 
			
		||||
        assertTrue(actualValues.contains(expected));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * id
 | 
			
		||||
     * WriteReplace {"id":"/19/0/0","value":"0081"}..
 | 
			
		||||
     */
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testWriteReplaceValueMultipleResourceAsSingleResource_Result_BAD_REQUEST_Value_Multi_Instance_Resource_must_be_in_Json_format() throws Exception {
 | 
			
		||||
        String objectInstanceIdVer_19 = (String) expectedObjectIdVerInstances.stream().filter(path -> ((String) path).contains("/" + BINARY_APP_DATA_CONTAINER)).findFirst().get();
 | 
			
		||||
        String expectedPath = objectInstanceIdVer_19 + "/" + resourceId_0;
 | 
			
		||||
        String expectedValue = "0081";
 | 
			
		||||
        String actualResult = sendRPCWriteStringById("WriteReplace", expectedPath, expectedValue);
 | 
			
		||||
        ObjectNode rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class);
 | 
			
		||||
        assertEquals(ResponseCode.BAD_REQUEST.getName(), rpcActualResult.get("result").asText());
 | 
			
		||||
        String actualValues = rpcActualResult.get("error").asText();
 | 
			
		||||
        String expected = "Value of Multi-Instance Resource must be in Json format!";
 | 
			
		||||
        assertTrue(actualValues.contains(expected));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * bad: singleResource, operation="R" - only read
 | 
			
		||||
     * WriteReplace {"id":"/3/0/9","value":90}
 | 
			
		||||
 | 
			
		||||
@ -33,7 +33,6 @@ import org.thingsboard.server.gen.transport.TransportProtos.GetAttributeResponse
 | 
			
		||||
import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;
 | 
			
		||||
import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig;
 | 
			
		||||
import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportServerHelper;
 | 
			
		||||
import org.thingsboard.server.transport.lwm2m.utils.LwM2MTransportUtil;
 | 
			
		||||
import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
 | 
			
		||||
import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext;
 | 
			
		||||
import org.thingsboard.server.transport.lwm2m.server.downlink.LwM2mDownlinkMsgHandler;
 | 
			
		||||
@ -42,6 +41,7 @@ import org.thingsboard.server.transport.lwm2m.server.downlink.TbLwM2MWriteRespon
 | 
			
		||||
import org.thingsboard.server.transport.lwm2m.server.log.LwM2MTelemetryLogService;
 | 
			
		||||
import org.thingsboard.server.transport.lwm2m.server.ota.LwM2MOtaUpdateService;
 | 
			
		||||
import org.thingsboard.server.transport.lwm2m.server.uplink.LwM2mUplinkMsgHandler;
 | 
			
		||||
import org.thingsboard.server.transport.lwm2m.utils.LwM2MTransportUtil;
 | 
			
		||||
import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl;
 | 
			
		||||
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
@ -191,7 +191,7 @@ public class DefaultLwM2MAttributesService implements LwM2MAttributesService {
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onAttributesUpdate(LwM2mClient lwM2MClient, List<TransportProtos.TsKvProto> tsKvProtos, boolean logFailedUpdateOfNonChangedValue) {
 | 
			
		||||
        log.trace("[{}] onAttributesUpdate [{}]", lwM2MClient.getEndpoint(), tsKvProtos);
 | 
			
		||||
        Map <String, TransportProtos.TsKvProto> attributesUpdate =  new ConcurrentHashMap<>();
 | 
			
		||||
        Map<String, TransportProtos.TsKvProto> attributesUpdate = new ConcurrentHashMap<>();
 | 
			
		||||
        tsKvProtos.forEach(tsKvProto -> {
 | 
			
		||||
            try {
 | 
			
		||||
                String pathIdVer = clientContext.getObjectIdByKeyNameFromProfile(lwM2MClient, tsKvProto.getKv().getKey());
 | 
			
		||||
@ -207,8 +207,8 @@ public class DefaultLwM2MAttributesService implements LwM2MAttributesService {
 | 
			
		||||
                        attributesUpdate.put(pathIdVer, tsKvProto);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            } catch (IllegalArgumentException e){
 | 
			
		||||
                log.error("Failed update resource ["+lwM2MClient.getEndpoint()+"] onAttributesUpdate:", e);
 | 
			
		||||
            } catch (IllegalArgumentException e) {
 | 
			
		||||
                log.error("Failed update resource [" + lwM2MClient.getEndpoint() + "] onAttributesUpdate:", e);
 | 
			
		||||
                String logMsg = String.format("%s: Failed update resource onAttributesUpdate %s.",
 | 
			
		||||
                        LOG_LWM2M_ERROR, e.getMessage());
 | 
			
		||||
                logService.log(lwM2MClient, logMsg);
 | 
			
		||||
@ -226,8 +226,8 @@ public class DefaultLwM2MAttributesService implements LwM2MAttributesService {
 | 
			
		||||
                try {
 | 
			
		||||
                    pushUpdateMultiToClientIfNeeded(lwM2MClient, resourceModel, (JsonElement) newValProto,
 | 
			
		||||
                            (Map<Integer, LwM2mResourceInstance>) oldResourceValue, pathIdVer, logFailedUpdateOfNonChangedValue);
 | 
			
		||||
                } catch (Exception e){
 | 
			
		||||
                    log.error("Failed update resource ["+lwM2MClient.getEndpoint()+"] onAttributesUpdate:", e);
 | 
			
		||||
                } catch (Exception e) {
 | 
			
		||||
                    log.error("Failed update resource [" + lwM2MClient.getEndpoint() + "] onAttributesUpdate:", e);
 | 
			
		||||
                    String logMsg = String.format("%s: Failed update resource onAttributesUpdate %s.",
 | 
			
		||||
                            LOG_LWM2M_ERROR, e.getMessage());
 | 
			
		||||
                    logService.log(lwM2MClient, logMsg);
 | 
			
		||||
@ -243,7 +243,7 @@ public class DefaultLwM2MAttributesService implements LwM2MAttributesService {
 | 
			
		||||
                    LOG_LWM2M_ERROR, versionedId, "null");
 | 
			
		||||
            logService.log(lwM2MClient, logMsg);
 | 
			
		||||
            log.error("Failed update resource [{}] [{}]", versionedId, "null");
 | 
			
		||||
        } else if ((oldValue == null)  || !valueEquals(newValue, oldValue)) {
 | 
			
		||||
        } else if ((oldValue == null) || !valueEquals(newValue, oldValue)) {
 | 
			
		||||
            TbLwM2MWriteReplaceRequest request = TbLwM2MWriteReplaceRequest.builder().versionedId(versionedId).value(newValue).timeout(clientContext.getRequestTimeout(lwM2MClient)).build();
 | 
			
		||||
            downlinkHandler.sendWriteReplaceRequest(lwM2MClient, request, new TbLwM2MWriteResponseCallback(uplinkHandler, logService, lwM2MClient, versionedId));
 | 
			
		||||
        } else if (logFailedUpdateOfNonChangedValue) {
 | 
			
		||||
@ -256,10 +256,10 @@ public class DefaultLwM2MAttributesService implements LwM2MAttributesService {
 | 
			
		||||
 | 
			
		||||
    private void pushUpdateMultiToClientIfNeeded(LwM2mClient client, ResourceModel resourceModel, JsonElement newValProto,
 | 
			
		||||
                                                 Map<Integer, LwM2mResourceInstance> valueOld, String versionedId,
 | 
			
		||||
                                                 boolean logFailedUpdateOfNonChangedValue) throws Exception {
 | 
			
		||||
        Map newValues = convertMultiResourceValuesFromJson(newValProto, resourceModel.type, versionedId);
 | 
			
		||||
                                                 boolean logFailedUpdateOfNonChangedValue) {
 | 
			
		||||
        Map<Integer, Object> newValues = convertMultiResourceValuesFromJson(newValProto, resourceModel.type, versionedId);
 | 
			
		||||
        if (newValues.size() > 0 && valueOld != null && valueOld.size() > 0) {
 | 
			
		||||
            valueOld.values().stream().forEach((v) -> {
 | 
			
		||||
            valueOld.values().forEach((v) -> {
 | 
			
		||||
                if (newValues.containsKey(v.getId())) {
 | 
			
		||||
                    if (valueEquals(newValues.get(v.getId()), v.getValue())) {
 | 
			
		||||
                        newValues.remove(v.getId());
 | 
			
		||||
 | 
			
		||||
@ -37,7 +37,6 @@ import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;
 | 
			
		||||
import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig;
 | 
			
		||||
import org.thingsboard.server.transport.lwm2m.secure.TbLwM2MSecurityInfo;
 | 
			
		||||
import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportContext;
 | 
			
		||||
import org.thingsboard.server.transport.lwm2m.server.LwM2mVersionedModelProvider;
 | 
			
		||||
import org.thingsboard.server.transport.lwm2m.server.ota.LwM2MOtaUpdateService;
 | 
			
		||||
import org.thingsboard.server.transport.lwm2m.server.session.LwM2MSessionManager;
 | 
			
		||||
import org.thingsboard.server.transport.lwm2m.server.store.TbLwM2MClientStore;
 | 
			
		||||
@ -71,7 +70,6 @@ public class LwM2mClientContextImpl implements LwM2mClientContext {
 | 
			
		||||
    private final TbLwM2MClientStore clientStore;
 | 
			
		||||
    private final LwM2MSessionManager sessionManager;
 | 
			
		||||
    private final TransportDeviceProfileCache deviceProfileCache;
 | 
			
		||||
    private final LwM2mVersionedModelProvider modelProvider;
 | 
			
		||||
 | 
			
		||||
    @Autowired
 | 
			
		||||
    @Lazy
 | 
			
		||||
@ -229,10 +227,7 @@ public class LwM2mClientContextImpl implements LwM2mClientContext {
 | 
			
		||||
                throw new LwM2MClientStateException(client.getState(), "Client is in invalid state.");
 | 
			
		||||
            }
 | 
			
		||||
            client.setRegistration(registration);
 | 
			
		||||
            onUplink(client);
 | 
			
		||||
            if (compareAndSetSleepFlag(client, false)) {
 | 
			
		||||
                sendMsgsAfterSleeping(client);
 | 
			
		||||
            } else {
 | 
			
		||||
            if (!awake(client)) {
 | 
			
		||||
                clientStore.put(client);
 | 
			
		||||
            }
 | 
			
		||||
        } finally {
 | 
			
		||||
@ -419,7 +414,7 @@ public class LwM2mClientContextImpl implements LwM2mClientContext {
 | 
			
		||||
                powerMode = PowerMode.DRX;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        if (PowerMode.DRX.equals(powerMode)) {
 | 
			
		||||
        if (PowerMode.DRX.equals(powerMode) || otaUpdateService.isOtaDownloading(client)) {
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
        client.lock();
 | 
			
		||||
@ -503,7 +498,7 @@ public class LwM2mClientContextImpl implements LwM2mClientContext {
 | 
			
		||||
                sleepTask.cancel(false);
 | 
			
		||||
            }
 | 
			
		||||
            Future<Void> task = context.getScheduler().schedule(() -> {
 | 
			
		||||
                if (uplinkTime == client.getLastUplinkTime()) {
 | 
			
		||||
                if (uplinkTime == client.getLastUplinkTime() && !otaUpdateService.isOtaDownloading(client)) {
 | 
			
		||||
                    asleep(client);
 | 
			
		||||
                }
 | 
			
		||||
                return null;
 | 
			
		||||
 | 
			
		||||
@ -300,14 +300,13 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im
 | 
			
		||||
                    String msgError = "";
 | 
			
		||||
                    if (resourceModelWrite.multiple) {
 | 
			
		||||
                        try {
 | 
			
		||||
                            Map value = convertMultiResourceValuesFromRpcBody(request.getValue(), resourceModelWrite.type, request.getObjectId());
 | 
			
		||||
                            Map<Integer, Object> value = convertMultiResourceValuesFromRpcBody(request.getValue(), resourceModelWrite.type, request.getObjectId());
 | 
			
		||||
                            downlink = new WriteRequest(contentFormat, resultIds.getObjectId(), resultIds.getObjectInstanceId(), resultIds.getResourceId(),
 | 
			
		||||
                                    value, resourceModelWrite.type);
 | 
			
		||||
                        } catch (Exception e) {
 | 
			
		||||
                            msgError = "Resource id=" + resultIds.toString() + ", value = " + request.getValue() +
 | 
			
		||||
                                    ", class = " + request.getValue().getClass().getSimpleName() + ". Format value is bad. Value for this Multi-Instance Resource must be in Json format!";
 | 
			
		||||
                        }
 | 
			
		||||
                    } else {
 | 
			
		||||
                    }
 | 
			
		||||
                    if (downlink == null) {
 | 
			
		||||
                        try {
 | 
			
		||||
                            downlink = this.getWriteRequestSingleResource(resourceModelWrite.type, contentFormat,
 | 
			
		||||
                                    resultIds.getObjectId(), resultIds.getObjectInstanceId(), resultIds.getResourceId(), request.getValue());
 | 
			
		||||
@ -319,15 +318,11 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im
 | 
			
		||||
                    if (downlink != null) {
 | 
			
		||||
                        sendSimpleRequest(client, downlink, request.getTimeout(), callback);
 | 
			
		||||
                    } else {
 | 
			
		||||
                        if (msgError.isEmpty()) {
 | 
			
		||||
                            msgError = "WriteRequest is null.";
 | 
			
		||||
                        }
 | 
			
		||||
                        callback.onValidationError(toString(request), msgError);
 | 
			
		||||
                    }
 | 
			
		||||
                } catch (Exception e) {
 | 
			
		||||
                    callback.onError(toString(request), e);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
            } else {
 | 
			
		||||
                callback.onValidationError(toString(request), "Resource " + request.getVersionedId() + " is not configured in the device profile!");
 | 
			
		||||
            }
 | 
			
		||||
@ -378,7 +373,7 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im
 | 
			
		||||
                    if (resourceModelWrite != null) {
 | 
			
		||||
                        if (resourceModelWrite.multiple) {
 | 
			
		||||
                            try {
 | 
			
		||||
                                Map value = convertMultiResourceValuesFromRpcBody(request.getValue(), resourceModelWrite.type, request.getObjectId());
 | 
			
		||||
                                Map<Integer, Object> value = convertMultiResourceValuesFromRpcBody(request.getValue(), resourceModelWrite.type, request.getObjectId());
 | 
			
		||||
                                downlink = new WriteRequest(WriteRequest.Mode.UPDATE, contentFormat, resultIds.getObjectId(),
 | 
			
		||||
                                        resultIds.getObjectInstanceId(), resultIds.getResourceId(),
 | 
			
		||||
                                        value, resourceModelWrite.type);
 | 
			
		||||
@ -608,7 +603,7 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im
 | 
			
		||||
        LwM2mPath pathIds = new LwM2mPath(fromVersionedIdToObjectId(versionedId));
 | 
			
		||||
        if (pathIds.isResource() || pathIds.isResourceInstance()) {
 | 
			
		||||
            ResourceModel resourceModel = client.getResourceModel(versionedId, modelProvider);
 | 
			
		||||
            if (resourceModel!= null && (pathIds.isResourceInstance() || (pathIds.isResource() && !resourceModel.multiple))) {
 | 
			
		||||
            if (resourceModel != null && (pathIds.isResourceInstance() || (pathIds.isResource() && !resourceModel.multiple))) {
 | 
			
		||||
                if (OBJLNK.equals(resourceModel.type)) {
 | 
			
		||||
                    return ContentFormat.LINK;
 | 
			
		||||
                } else if (OPAQUE.equals(resourceModel.type)) {
 | 
			
		||||
 | 
			
		||||
@ -182,8 +182,8 @@ public class DefaultLwM2MOtaUpdateService extends LwM2MExecutorAwareService impl
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        var clientSettings = clientContext.getProfile(client.getProfileId()).getClientLwM2mSettings();
 | 
			
		||||
        onFirmwareStrategyUpdate(client, clientSettings);
 | 
			
		||||
        onCurrentSoftwareStrategyUpdate(client, clientSettings);
 | 
			
		||||
        initFwStrategy(client, clientSettings);
 | 
			
		||||
        initSwStrategy(client, clientSettings);
 | 
			
		||||
 | 
			
		||||
        if (!attributesToFetch.isEmpty()) {
 | 
			
		||||
            var future = attributesService.getSharedAttributes(client, attributesToFetch);
 | 
			
		||||
@ -193,7 +193,7 @@ public class DefaultLwM2MOtaUpdateService extends LwM2MExecutorAwareService impl
 | 
			
		||||
                    Optional<String> newFwVersion = getAttributeValue(attrs, FIRMWARE_VERSION);
 | 
			
		||||
                    Optional<String> newFwTag = getAttributeValue(attrs, FIRMWARE_TAG);
 | 
			
		||||
                    Optional<String> newFwUrl = getAttributeValue(attrs, FIRMWARE_URL);
 | 
			
		||||
                    if (newFwTitle.isPresent() && newFwVersion.isPresent()) {
 | 
			
		||||
                    if (newFwTitle.isPresent() && newFwVersion.isPresent() && !isOtaDownloading(client) && !UPDATING.equals(fwInfo.status)) {
 | 
			
		||||
                        onTargetFirmwareUpdate(client, newFwTitle.get(), newFwVersion.get(), newFwUrl, newFwTag);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
@ -245,19 +245,27 @@ public class DefaultLwM2MOtaUpdateService extends LwM2MExecutorAwareService impl
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onFirmwareStrategyUpdate(LwM2mClient client, OtherConfiguration configuration) {
 | 
			
		||||
        log.debug("[{}] Current fw strategy: {}", client.getEndpoint(), configuration.getFwUpdateStrategy());
 | 
			
		||||
        startFirmwareUpdateIfNeeded(client, initFwStrategy(client, configuration));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private LwM2MClientFwOtaInfo initFwStrategy(LwM2mClient client, OtherConfiguration configuration) {
 | 
			
		||||
        LwM2MClientFwOtaInfo fwInfo = getOrInitFwInfo(client);
 | 
			
		||||
        fwInfo.setStrategy(LwM2MFirmwareUpdateStrategy.fromStrategyFwByCode(configuration.getFwUpdateStrategy()));
 | 
			
		||||
        fwInfo.setBaseUrl(configuration.getFwUpdateResource());
 | 
			
		||||
        startFirmwareUpdateIfNeeded(client, fwInfo);
 | 
			
		||||
        return fwInfo;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onCurrentSoftwareStrategyUpdate(LwM2mClient client, OtherConfiguration configuration) {
 | 
			
		||||
        log.debug("[{}] Current sw strategy: {}", client.getEndpoint(), configuration.getSwUpdateStrategy());
 | 
			
		||||
        startSoftwareUpdateIfNeeded(client, initSwStrategy(client, configuration));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private LwM2MClientSwOtaInfo initSwStrategy(LwM2mClient client, OtherConfiguration configuration) {
 | 
			
		||||
        LwM2MClientSwOtaInfo swInfo = getOrInitSwInfo(client);
 | 
			
		||||
        swInfo.setStrategy(LwM2MSoftwareUpdateStrategy.fromStrategySwByCode(configuration.getSwUpdateStrategy()));
 | 
			
		||||
        swInfo.setBaseUrl(configuration.getSwUpdateResource());
 | 
			
		||||
        startSoftwareUpdateIfNeeded(client, swInfo);
 | 
			
		||||
        return swInfo;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
@ -308,6 +316,7 @@ public class DefaultLwM2MOtaUpdateService extends LwM2MExecutorAwareService impl
 | 
			
		||||
        if (FirmwareUpdateResult.INITIAL.equals(result) && OtaPackageUpdateStatus.UPDATING.equals(fwInfo.getStatus())) {
 | 
			
		||||
            status = Optional.of(UPDATED);
 | 
			
		||||
            fwInfo.setRetryAttempts(0);
 | 
			
		||||
            fwInfo.setFailedPackageId(null);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        status.ifPresent(otaStatus -> {
 | 
			
		||||
@ -388,6 +397,22 @@ public class DefaultLwM2MOtaUpdateService extends LwM2MExecutorAwareService impl
 | 
			
		||||
        startSoftwareUpdateIfNeeded(client, fwInfo);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean isOtaDownloading(LwM2mClient client) {
 | 
			
		||||
        String endpoint = client.getEndpoint();
 | 
			
		||||
        LwM2MClientFwOtaInfo fwInfo = fwStates.get(endpoint);
 | 
			
		||||
        LwM2MClientSwOtaInfo swInfo = swStates.get(endpoint);
 | 
			
		||||
 | 
			
		||||
        if (fwInfo != null && (DOWNLOADING.equals(fwInfo.getStatus()))) {
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
        if (swInfo != null && (DOWNLOADING.equals(swInfo.getStatus()))) {
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void startFirmwareUpdateIfNeeded(LwM2mClient client, LwM2MClientFwOtaInfo fwInfo) {
 | 
			
		||||
        try {
 | 
			
		||||
            if (!fwInfo.isSupported() && fwInfo.isAssigned()) {
 | 
			
		||||
@ -401,7 +426,7 @@ public class DefaultLwM2MOtaUpdateService extends LwM2MExecutorAwareService impl
 | 
			
		||||
                    log.debug("[{}] Starting update to [{}{}] using binary", client.getEndpoint(), fwInfo.getTargetName(), fwInfo.getTargetVersion());
 | 
			
		||||
                    startUpdateUsingBinary(client, fwInfo);
 | 
			
		||||
                }
 | 
			
		||||
            } else if (fwInfo.getResult() != null && fwInfo.getResult().getCode() >  UPDATE_SUCCESSFULLY.getCode()) {
 | 
			
		||||
            } else if (fwInfo.getResult() != null && fwInfo.getResult().getCode() > UPDATE_SUCCESSFULLY.getCode()) {
 | 
			
		||||
                log.trace("[{}] Previous update failed. [{}]", client.getEndpoint(), fwInfo);
 | 
			
		||||
                logService.log(client, "Previous update firmware failed. Result: " + fwInfo.getResult().name());
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@ -55,4 +55,6 @@ public interface LwM2MOtaUpdateService {
 | 
			
		||||
    void onCurrentSoftwareStateUpdate(LwM2mClient lwM2MClient, Long value);
 | 
			
		||||
 | 
			
		||||
    void onCurrentSoftwareResultUpdate(LwM2mClient client, Long result);
 | 
			
		||||
 | 
			
		||||
    boolean isOtaDownloading(LwM2mClient client);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -278,11 +278,9 @@ public class DefaultLwM2MRpcRequestHandler implements LwM2MRpcRequestHandler {
 | 
			
		||||
            ResourceModel resourceModel = client.getResourceModel(versionedId, modelProvider);
 | 
			
		||||
            if (resourceModel != null && resourceModel.multiple) {
 | 
			
		||||
                try {
 | 
			
		||||
                    Map value = convertMultiResourceValuesFromRpcBody(requestBody.getValue(), resourceModel.type, versionedId);
 | 
			
		||||
                    Map<Integer, Object> value = convertMultiResourceValuesFromRpcBody(requestBody.getValue(), resourceModel.type, versionedId);
 | 
			
		||||
                    requestBody.setValue(value);
 | 
			
		||||
                } catch (Exception e) {
 | 
			
		||||
                    throw new IllegalArgumentException("Resource id=" + versionedId + ", class = " +
 | 
			
		||||
                            requestBody.getValue().getClass().getSimpleName() + ", value = " + requestBody.getValue() + " is bad. Value of Multi-Instance Resource must be in Json format!");
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
@ -304,7 +302,7 @@ public class DefaultLwM2MRpcRequestHandler implements LwM2MRpcRequestHandler {
 | 
			
		||||
     */
 | 
			
		||||
    private void sendWriteCompositeRequest(LwM2mClient client, TransportProtos.ToDeviceRpcRequestMsg requestMsg, ContentFormat contentFormatComposite) {
 | 
			
		||||
        RpcWriteCompositeRequest rpcWriteCompositeRequest = JacksonUtil.fromString(requestMsg.getParams(), RpcWriteCompositeRequest.class);
 | 
			
		||||
        Map validNodes = validateNodes(client, rpcWriteCompositeRequest.getNodes());
 | 
			
		||||
        Map<String, Object> validNodes = validateNodes(client, rpcWriteCompositeRequest.getNodes());
 | 
			
		||||
        if (validNodes.size() > 0) {
 | 
			
		||||
            rpcWriteCompositeRequest.setNodes(validNodes);
 | 
			
		||||
            var mainCallback = new TbLwM2MWriteResponseCompositeCallback(uplinkHandler, logService, client, null);
 | 
			
		||||
@ -315,22 +313,21 @@ public class DefaultLwM2MRpcRequestHandler implements LwM2MRpcRequestHandler {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private Map validateNodes(LwM2mClient client, Map nodes) {
 | 
			
		||||
        Map newNodes = new LinkedHashMap();
 | 
			
		||||
    private Map<String, Object> validateNodes(LwM2mClient client, Map<String, Object> nodes) {
 | 
			
		||||
        Map<String, Object> newNodes = new LinkedHashMap<>();
 | 
			
		||||
        nodes.forEach((key, value) -> {
 | 
			
		||||
            String versionedId;
 | 
			
		||||
            try {
 | 
			
		||||
                // validate key.toString()
 | 
			
		||||
                LwM2mPath path = new LwM2mPath(fromVersionedIdToObjectId(key.toString()));
 | 
			
		||||
                LwM2mPath path = new LwM2mPath(fromVersionedIdToObjectId(key));
 | 
			
		||||
                if (path.isResource() || path.isResourceInstance()) {
 | 
			
		||||
                    versionedId = key.toString();
 | 
			
		||||
                    versionedId = key;
 | 
			
		||||
                }
 | 
			
		||||
                else {
 | 
			
		||||
                    throw new IllegalArgumentException(String.format("nodes: %s is not validate value. " +
 | 
			
		||||
                            "The WriteComposite operation is only used for SingleResources or/and ResourceInstance.", nodes.toString()));
 | 
			
		||||
                }
 | 
			
		||||
            } catch (Exception e) {
 | 
			
		||||
                versionedId = clientContext.getObjectIdByKeyNameFromProfile(client, key.toString());
 | 
			
		||||
                versionedId = clientContext.getObjectIdByKeyNameFromProfile(client, key);
 | 
			
		||||
            }
 | 
			
		||||
            // validate value. Must be only primitive, not JsonObject or JsonArray
 | 
			
		||||
            try {
 | 
			
		||||
 | 
			
		||||
@ -351,14 +351,14 @@ public class LwM2MTransportUtil {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Map convertMultiResourceValuesFromRpcBody(Object value, ResourceModel.Type type, String versionedId) throws Exception {
 | 
			
		||||
    public static Map<Integer, Object> convertMultiResourceValuesFromRpcBody(Object value, ResourceModel.Type type, String versionedId) throws Exception {
 | 
			
		||||
            String valueJsonStr = JsonUtils.writeValueAsString(value);
 | 
			
		||||
            JsonElement element = JsonUtils.parse(valueJsonStr);
 | 
			
		||||
            return convertMultiResourceValuesFromJson(element, type, versionedId);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Map convertMultiResourceValuesFromJson(JsonElement newValProto, ResourceModel.Type type, String versionedId)  throws Exception{
 | 
			
		||||
        Map newValues = equalsMultiResourceValuesResourceType(type);
 | 
			
		||||
    public static Map<Integer, Object> convertMultiResourceValuesFromJson(JsonElement newValProto, ResourceModel.Type type, String versionedId) {
 | 
			
		||||
        Map<Integer, Object> newValues = new HashMap<>();
 | 
			
		||||
        newValProto.getAsJsonObject().entrySet().forEach((obj) -> {
 | 
			
		||||
            newValues.put(Integer.valueOf(obj.getKey()), LwM2mValueConverterImpl.getInstance().convertValue(obj.getValue().getAsString(),
 | 
			
		||||
                    STRING, type, new LwM2mPath(fromVersionedIdToObjectId(versionedId))));
 | 
			
		||||
@ -366,27 +366,6 @@ public class LwM2MTransportUtil {
 | 
			
		||||
        return newValues;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Map equalsMultiResourceValuesResourceType(ResourceModel.Type type) {
 | 
			
		||||
        switch (type) {
 | 
			
		||||
            case FLOAT:
 | 
			
		||||
                return new HashMap<Integer, Float>();
 | 
			
		||||
            case INTEGER:
 | 
			
		||||
                return new HashMap<Integer, Integer>();
 | 
			
		||||
            case STRING:
 | 
			
		||||
                return new HashMap<Integer, String>();
 | 
			
		||||
            case BOOLEAN:
 | 
			
		||||
                return new HashMap<Integer, Boolean>();
 | 
			
		||||
            case OPAQUE:
 | 
			
		||||
                return new HashMap<Integer, byte[]>();
 | 
			
		||||
            case TIME:
 | 
			
		||||
                return new HashMap<Integer, Date>();
 | 
			
		||||
            case OBJLNK:
 | 
			
		||||
                return new HashMap<Integer, ObjectLink>();
 | 
			
		||||
            default:
 | 
			
		||||
                return null;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Object convertWriteAttributes(String type, Object value, DefaultLwM2mUplinkMsgHandler serviceImpl, String target) {
 | 
			
		||||
        switch (type) {
 | 
			
		||||
            /** Integer [0:255]; */
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user