From 6e6d57e60ab1e9ba4bf375b4eef60166ad66ac4a Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Fri, 28 Feb 2025 15:34:21 +0200 Subject: [PATCH 01/16] UI: Add support use Obj19 for OTA updated in LWM2M transport configuration --- ...ile-transport-configuration.component.html | 74 ++++++++++--------- ...ofile-transport-configuration.component.ts | 2 + .../lwm2m/lwm2m-profile-config.models.ts | 7 +- .../assets/locale/locale.constant-en_US.json | 6 +- 4 files changed, 53 insertions(+), 36 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-profile-transport-configuration.component.html b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-profile-transport-configuration.component.html index 0ad27b23ef..bb37b5784a 100644 --- a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-profile-transport-configuration.component.html +++ b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-profile-transport-configuration.component.html @@ -52,39 +52,47 @@
- device-profile.lwm2m.fw-update - - {{ 'device-profile.lwm2m.fw-update-strategy' | translate }} - - {{ 'device-profile.lwm2m.fw-update-strategy-package' | translate }} - {{ 'device-profile.lwm2m.fw-update-strategy-package-uri' | translate }} - {{ 'device-profile.lwm2m.fw-update-strategy-data' | translate }} - - - - {{ 'device-profile.lwm2m.fw-update-resource' | translate }} - - - {{ 'device-profile.lwm2m.fw-update-resource-required' | translate }} - - -
-
- device-profile.lwm2m.sw-update - - {{ 'device-profile.lwm2m.sw-update-strategy' | translate }} - - {{ 'device-profile.lwm2m.sw-update-strategy-package' | translate }} - {{ 'device-profile.lwm2m.sw-update-strategy-package-uri' | translate }} - - - - {{ 'device-profile.lwm2m.sw-update-resource' | translate }} - - - {{ 'device-profile.lwm2m.sw-update-resource-required' | translate }} - - + device-profile.lwm2m.ota-update + + + {{ 'device-profile.lwm2m.use-object-19-for-ota-update' | translate }} + + +
+ device-profile.lwm2m.fw-update + + {{ 'device-profile.lwm2m.fw-update-strategy' | translate }} + + {{ 'device-profile.lwm2m.fw-update-strategy-package' | translate }} + {{ 'device-profile.lwm2m.fw-update-strategy-package-uri' | translate }} + {{ 'device-profile.lwm2m.fw-update-strategy-data' | translate }} + + + + {{ 'device-profile.lwm2m.fw-update-resource' | translate }} + + + {{ 'device-profile.lwm2m.fw-update-resource-required' | translate }} + + +
+
+ device-profile.lwm2m.sw-update + + {{ 'device-profile.lwm2m.sw-update-strategy' | translate }} + + {{ 'device-profile.lwm2m.sw-update-strategy-package' | translate }} + {{ 'device-profile.lwm2m.sw-update-strategy-package-uri' | translate }} + + + + {{ 'device-profile.lwm2m.sw-update-resource' | translate }} + + + {{ 'device-profile.lwm2m.sw-update-resource-required' | translate }} + + +
device-profile.power-saving-mode diff --git a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-profile-transport-configuration.component.ts b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-profile-transport-configuration.component.ts index a9fbb7b249..46c439cf33 100644 --- a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-profile-transport-configuration.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-profile-transport-configuration.component.ts @@ -104,6 +104,7 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro bootstrap: [[]], clientLwM2mSettings: this.fb.group({ clientOnlyObserveAfterConnect: [1, []], + useObject19ForOta: [false], fwUpdateStrategy: [1, []], swUpdateStrategy: [1, []], fwUpdateResource: [{value: '', disabled: true}, []], @@ -262,6 +263,7 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro bootstrapServerUpdateEnable: this.configurationValue.bootstrapServerUpdateEnable || false, clientLwM2mSettings: { clientOnlyObserveAfterConnect: this.configurationValue.clientLwM2mSettings.clientOnlyObserveAfterConnect, + useObject19ForOta: this.configurationValue.clientLwM2mSettings.useObject19ForOta ?? false, fwUpdateStrategy: this.configurationValue.clientLwM2mSettings.fwUpdateStrategy || 1, swUpdateStrategy: this.configurationValue.clientLwM2mSettings.swUpdateStrategy || 1, fwUpdateResource: this.configurationValue.clientLwM2mSettings.fwUpdateResource || '', diff --git a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-profile-config.models.ts b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-profile-config.models.ts index e5706cf39b..33b358e581 100644 --- a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-profile-config.models.ts +++ b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-profile-config.models.ts @@ -124,13 +124,15 @@ export const PowerModeTranslationMap = new Map( export enum ObjectIDVer { V1_0 = '1.0', - V1_1 = '1.1' + V1_1 = '1.1', + V1_2 = '1.2', } export const ObjectIDVerTranslationMap = new Map( [ [ObjectIDVer.V1_0, 'device-profile.lwm2m.default-object-id-ver.v1-0'], - [ObjectIDVer.V1_1, 'device-profile.lwm2m.default-object-id-ver.v1-1'] + [ObjectIDVer.V1_1, 'device-profile.lwm2m.default-object-id-ver.v1-1'], + [ObjectIDVer.V1_2, 'device-profile.lwm2m.default-object-id-ver.v1-2'], ] ); @@ -167,6 +169,7 @@ export interface Lwm2mProfileConfigModels { export interface ClientLwM2mSettings { clientOnlyObserveAfterConnect: number; + useObject19ForOta?: boolean; fwUpdateStrategy: number; swUpdateStrategy: number; fwUpdateResource?: string; diff --git a/ui-ngx/src/assets/locale/locale.constant-en_US.json b/ui-ngx/src/assets/locale/locale.constant-en_US.json index de97184f5a..67b406fc40 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -2077,6 +2077,9 @@ "add-lwm2m-server-config": "Add LwM2M server", "no-config-servers": "No servers configured", "others-tab": "Other settings", + "ota-update": "OTA update", + "use-object-19-for-ota-update": "Use Object 19 for OTA update", + "use-object-19-for-ota-update-hint": "Use Resource ObjectId = 19 for OTA updates: FirmWare → InstanceId = 65534, SoftWare → InstanceId = 65535. The data format is JSON wrapped in Base64. The main field in JSON: \"Checksum\" (SHA256). Additional fields: \"Title\" (OTA name), \"Version\" (OTA version), \"File Name\" (file name for storing OTA on the client), \"File Size\" (OTA size in bytes).", "client-strategy": "Client strategy when connecting", "client-strategy-label": "Strategy", "client-strategy-only-observe": "Only Observe Request to the client after the initial connection", @@ -2107,7 +2110,8 @@ "default-object-id": "Default Object Version (Attribute)", "default-object-id-ver": { "v1-0": "1.0", - "v1-1": "1.1" + "v1-1": "1.1", + "v1-2": "1.2" } }, "snmp": { From bb31dd5c909a5a5817c175722d55e9920b9527b9 Mon Sep 17 00:00:00 2001 From: nick Date: Fri, 28 Feb 2025 15:56:53 +0200 Subject: [PATCH 02/16] lwm2m: backend: add useObject19ForOta --- .../server/service/device/DeviceBulkImportService.java | 2 +- .../common/data/device/profile/lwm2m/OtherConfiguration.java | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/application/src/main/java/org/thingsboard/server/service/device/DeviceBulkImportService.java b/application/src/main/java/org/thingsboard/server/service/device/DeviceBulkImportService.java index b895614bdc..2924f8ddeb 100644 --- a/application/src/main/java/org/thingsboard/server/service/device/DeviceBulkImportService.java +++ b/application/src/main/java/org/thingsboard/server/service/device/DeviceBulkImportService.java @@ -257,7 +257,7 @@ public class DeviceBulkImportService extends AbstractBulkImportService { Lwm2mDeviceProfileTransportConfiguration transportConfiguration = new Lwm2mDeviceProfileTransportConfiguration(); transportConfiguration.setBootstrap(Collections.emptyList()); - transportConfiguration.setClientLwM2mSettings(new OtherConfiguration(1, 1, 1, PowerMode.DRX, null, null, null, null, null, V1_0.toString())); + transportConfiguration.setClientLwM2mSettings(new OtherConfiguration(false,1, 1, 1, PowerMode.DRX, null, null, null, null, null, V1_0.toString())); transportConfiguration.setObserveAttr(new TelemetryMappingConfiguration(Collections.emptyMap(), Collections.emptySet(), Collections.emptySet(), Collections.emptySet(), Collections.emptyMap())); DeviceProfileData deviceProfileData = new DeviceProfileData(); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/OtherConfiguration.java b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/OtherConfiguration.java index 8eabff8ed8..0d59ef6f8f 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/OtherConfiguration.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/OtherConfiguration.java @@ -30,6 +30,7 @@ import org.thingsboard.server.common.data.device.data.PowerSavingConfiguration; @JsonIgnoreProperties(ignoreUnknown = true) public class OtherConfiguration extends PowerSavingConfiguration { + private Boolean useObject19ForOta; private Integer fwUpdateStrategy; private Integer swUpdateStrategy; private Integer clientOnlyObserveAfterConnect; From 5f2bb68bc829dd6276f66fdfaee93ef5cbaf64cc Mon Sep 17 00:00:00 2001 From: nickAS21 Date: Wed, 9 Apr 2025 18:48:31 +0300 Subject: [PATCH 03/16] lwm2m: add params FOTA to object 19 --- .../DefaultLwM2mDownlinkMsgHandler.java | 4 +- .../ota/DefaultLwM2MOtaUpdateService.java | 81 +++++++++++++++++-- .../lwm2m/server/ota/LwM2MClientOtaInfo.java | 12 ++- .../common/transport/util/JsonUtils.java | 16 +++- 4 files changed, 99 insertions(+), 14 deletions(-) diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/DefaultLwM2mDownlinkMsgHandler.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/DefaultLwM2mDownlinkMsgHandler.java index 12bc176fe3..ed685dfc6c 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/DefaultLwM2mDownlinkMsgHandler.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/DefaultLwM2mDownlinkMsgHandler.java @@ -113,6 +113,7 @@ import static org.eclipse.leshan.core.link.lwm2m.attributes.LwM2mAttributes.SHOR import static org.eclipse.leshan.core.link.lwm2m.attributes.LwM2mAttributes.STEP; import static org.eclipse.leshan.core.model.ResourceModel.Type.OBJLNK; import static org.eclipse.leshan.core.model.ResourceModel.Type.OPAQUE; +import static org.thingsboard.server.common.transport.util.JsonUtils.isBase64; import static org.thingsboard.server.transport.lwm2m.utils.LwM2MTransportUtil.convertMultiResourceValuesFromRpcBody; import static org.thingsboard.server.transport.lwm2m.utils.LwM2MTransportUtil.createModelsDefault; import static org.thingsboard.server.transport.lwm2m.utils.LwM2MTransportUtil.fromVersionedIdToObjectId; @@ -399,7 +400,8 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im try { Object valueForMultiResource = request.getValue(); if (resultIds.isResourceInstance()) { - String resourceInstance = "{" + resultIds.getResourceInstanceId() + "=" + request.getValue() + "}"; + String valueStr = isBase64(request.getValue().toString()) ? "\"" + request.getValue() + "\"" : request.getValue().toString(); + String resourceInstance = "{" + resultIds.getResourceInstanceId() + "=" + valueStr + "}"; valueForMultiResource = JsonParser.parseString(resourceInstance); } Map value = convertMultiResourceValuesFromRpcBody(valueForMultiResource, resourceModelWrite.type, request.getObjectId()); diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/DefaultLwM2MOtaUpdateService.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/DefaultLwM2MOtaUpdateService.java index 2f2407e451..8ed9c69755 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/DefaultLwM2MOtaUpdateService.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/DefaultLwM2MOtaUpdateService.java @@ -15,16 +15,21 @@ */ package org.thingsboard.server.transport.lwm2m.server.ota; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.google.common.hash.Hashing; import jakarta.annotation.PostConstruct; import jakarta.annotation.PreDestroy; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.eclipse.leshan.core.model.ObjectModel; +import org.eclipse.leshan.core.node.LwM2mPath; import org.eclipse.leshan.core.node.codec.CodecException; import org.eclipse.leshan.core.request.ContentFormat; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.thingsboard.common.util.DonAsynchron; +import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.cache.ota.OtaPackageDataCache; import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.device.profile.lwm2m.OtherConfiguration; @@ -37,15 +42,12 @@ import org.thingsboard.server.gen.transport.TransportProtos; 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.server.LwM2mVersionedModelProvider; import org.thingsboard.server.transport.lwm2m.server.attributes.LwM2MAttributesService; 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.common.LwM2MExecutorAwareService; -import org.thingsboard.server.transport.lwm2m.server.downlink.LwM2mDownlinkMsgHandler; -import org.thingsboard.server.transport.lwm2m.server.downlink.TbLwM2MExecuteCallback; -import org.thingsboard.server.transport.lwm2m.server.downlink.TbLwM2MExecuteRequest; -import org.thingsboard.server.transport.lwm2m.server.downlink.TbLwM2MWriteReplaceRequest; -import org.thingsboard.server.transport.lwm2m.server.downlink.TbLwM2MWriteResponseCallback; +import org.thingsboard.server.transport.lwm2m.server.downlink.*; import org.thingsboard.server.transport.lwm2m.server.log.LwM2MTelemetryLogService; import org.thingsboard.server.transport.lwm2m.server.ota.firmware.FirmwareDeliveryMethod; import org.thingsboard.server.transport.lwm2m.server.ota.firmware.FirmwareUpdateResult; @@ -56,6 +58,7 @@ import org.thingsboard.server.transport.lwm2m.server.ota.software.LwM2MClientSwO import org.thingsboard.server.transport.lwm2m.server.ota.software.LwM2MSoftwareUpdateStrategy; import org.thingsboard.server.transport.lwm2m.server.ota.software.SoftwareUpdateResult; import org.thingsboard.server.transport.lwm2m.server.ota.software.SoftwareUpdateState; +import org.thingsboard.server.transport.lwm2m.server.rpc.RpcCreateRequest; import org.thingsboard.server.transport.lwm2m.server.store.TbLwM2MClientOtaInfoStore; import org.thingsboard.server.transport.lwm2m.server.uplink.LwM2mUplinkMsgHandler; @@ -64,6 +67,7 @@ import java.util.List; import java.util.Map; import java.util.Optional; import java.util.UUID; +import java.util.Base64; import java.util.concurrent.ConcurrentHashMap; import static org.thingsboard.server.common.data.ota.OtaPackageKey.STATE; @@ -104,6 +108,14 @@ public class DefaultLwM2MOtaUpdateService extends LwM2MExecutorAwareService impl public static final String FW_RESULT_ID = "/5/0/5"; public static final String FW_NAME_ID = "/5/0/6"; public static final String FW_VER_ID = "/5/0/7"; + public static final String FW_INFO_19_INSTANCE_ID = "/19/65534"; + public static final String SW_INFO_19_INSTANCE_ID = "/19/65535"; + public static final String OTA_INFO_19_TITLE = "title"; + public static final String OTA_INFO_19_VERSION = "version"; + public static final String OTA_INFO_19_FILE_CHECKSUM256 = "fileChecksumSHA256"; + public static final String OTA_INFO_19_FILE_SIZE = "fileSize"; + public static final String OTA_INFO_19_FILE_NAME = "fileName"; + /** * Quectel@Hi15RM1-HLB_V1.0@BC68JAR01A10,V150R100C20B300SP7,V150R100C20B300SP7@8 * Revision:BC68JAR01A10 @@ -134,6 +146,7 @@ public class DefaultLwM2MOtaUpdateService extends LwM2MExecutorAwareService impl private final LwM2MTelemetryLogService logService; private final LwM2mTransportServerHelper helper; private final TbLwM2MClientOtaInfoStore otaInfoStore; + private final LwM2mVersionedModelProvider modelProvider; @Autowired @Lazy @@ -510,6 +523,9 @@ public class DefaultLwM2MOtaUpdateService extends LwM2MExecutorAwareService impl } else { strategy = info.getDeliveryMethod() == FirmwareDeliveryMethod.PULL.code ? LwM2MFirmwareUpdateStrategy.OBJ_5_TEMP_URL : LwM2MFirmwareUpdateStrategy.OBJ_5_BINARY; } + if (clientContext.getProfile(client.getProfileId()).getClientLwM2mSettings().getUseObject19ForOta()){ + sendInfoFwToObject19ForOta(client, convertObjectIdToVersionedId(FW_INFO_19_INSTANCE_ID, client), response, otaPackageId); + } switch (strategy) { case OBJ_5_BINARY: startUpdateUsingBinary(client, convertObjectIdToVersionedId(FW_PACKAGE_5_ID, client), otaPackageId); @@ -641,6 +657,61 @@ public class DefaultLwM2MOtaUpdateService extends LwM2MExecutorAwareService impl helper.sendParametersOnThingsboardTelemetry(result, client.getSession(), client.getKeyTsLatestMap()); } + /** + * send to client: versionedId="/19/65534/0/0, value = FwOtaInfo in bas64 -> format json: + * {"title":"BC68JAR01", + * "version":"A10", + * "fileChecksumSHA256":"f2a08d4963e981c78f2a99f62d8439af4437a72ea7267a8c01d013c072c01ded", + * "fileSize":59832} + * @param client + * @param targetIdVer + * @param response + * @param otaPackageId + */ + private void sendInfoFwToObject19ForOta(LwM2mClient client, String targetIdVer, TransportProtos.GetOtaPackageResponseMsg response, UUID otaPackageId) { + log.trace("[{}] Current info fw toObject19ForOta", client.getEndpoint()); + ObjectModel objectModel = client.getObjectModel(targetIdVer, modelProvider); + if (objectModel != null) { + try { + if (client.getRegistration().getSupportedObject().get(19) != null) { + ObjectNode objectNodeInfoFw = JacksonUtil.newObjectNode(); + byte[] firmwareChunk = otaPackageDataCache.get(otaPackageId.toString(), 0, 0); + String fileChecksumSHA256 = Hashing.sha256().hashBytes(firmwareChunk).toString(); + objectNodeInfoFw.put(OTA_INFO_19_TITLE, response.getTitle()); + objectNodeInfoFw.put(OTA_INFO_19_VERSION, response.getVersion()); + objectNodeInfoFw.put(OTA_INFO_19_FILE_CHECKSUM256, fileChecksumSHA256); + objectNodeInfoFw.put(OTA_INFO_19_FILE_SIZE, firmwareChunk.length); + objectNodeInfoFw.put(OTA_INFO_19_FILE_NAME, response.getFileName()); + String objectNodeInfoFwStr = JacksonUtil.toString(objectNodeInfoFw); + assert objectNodeInfoFwStr != null; + String objectNodeInfoFwBase64 = Base64.getEncoder().encodeToString(objectNodeInfoFwStr.getBytes()); + + + LwM2mPath pathFwInstance = new LwM2mPath(FW_INFO_19_INSTANCE_ID); + if (client.getRegistration().getAvailableInstances().contains(pathFwInstance)) { + String versionId = targetIdVer + "/0/0"; + TbLwM2MWriteReplaceRequest request = TbLwM2MWriteReplaceRequest.builder().versionedId(versionId).value(objectNodeInfoFwBase64).timeout(clientContext.getRequestTimeout(client)).build(); + downlinkHandler.sendWriteReplaceRequest(client, request, new TbLwM2MWriteResponseCallback(uplinkHandler, logService, client, versionId)); + } else { + String valueResourcesStr = "{\"" + 0 + "\":{\"0\":\"" + objectNodeInfoFwBase64 + "\"}}"; + String valueStr = "{\"id\":\"" + targetIdVer + "\",\"value\":" + valueResourcesStr + "}"; + RpcCreateRequest requestBody = JacksonUtil.fromString(valueStr, RpcCreateRequest.class); + assert requestBody != null; + TbLwM2MCreateRequest.TbLwM2MCreateRequestBuilder builder = TbLwM2MCreateRequest.builder().versionedId(targetIdVer); + builder.value(requestBody.getValue()).nodes(requestBody.getNodes()).timeout(clientContext.getRequestTimeout(client)); + downlinkHandler.sendCreateRequest(client, builder.build(), new TbLwM2MCreateResponseCallback(uplinkHandler, logService, client, targetIdVer)); + } + } else { + String errorMsg = "Failed to send Info Fw to object 19. The client does not have object 19."; + log.trace("[{}] {}", client.getEndpoint(), errorMsg); + logService.log(client, errorMsg); + } + } catch (Exception e){ + log.error("", e); + } + } + } + private static Optional toOtaPackageUpdateStatus(FirmwareUpdateResult fwUpdateResult) { switch (fwUpdateResult) { case INITIAL: diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/LwM2MClientOtaInfo.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/LwM2MClientOtaInfo.java index b5ec94d48b..d1a8052610 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/LwM2MClientOtaInfo.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/LwM2MClientOtaInfo.java @@ -74,18 +74,16 @@ public abstract class LwM2MClientOtaInfo { } else { if (targetPackageId.equals(currentPackageId)) { return false; - } else if (StringUtils.isNotEmpty(targetTag) && targetTag.equals(currentPackageId)) { - return false; - } else if (StringUtils.isNotEmpty(currentVersion3)) { - if (StringUtils.isNotEmpty(targetTag) && currentVersion3.contains(targetTag)) { + } else{ + if (targetTag.equals(currentPackageId)) { return false; + } else if (StringUtils.isNotEmpty(currentVersion3)) { + return !(currentVersion3.contains(targetTag) || targetTag.contains(currentVersion3)); } - return !currentVersion3.contains(targetPackageId); - } else { - return true; } } } + return true; } @JsonIgnore diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/util/JsonUtils.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/util/JsonUtils.java index 28a904edb9..a79d897daf 100644 --- a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/util/JsonUtils.java +++ b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/util/JsonUtils.java @@ -23,9 +23,13 @@ import org.thingsboard.server.gen.transport.TransportProtos.KeyValueProto; import java.util.List; import java.util.Map; +import java.util.regex.Pattern; public class JsonUtils { + private static final Pattern BASE64_PATTERN = + Pattern.compile("^[A-Za-z0-9+/]+={0,2}$"); + public static JsonObject getJsonObject(List tsKv) { JsonObject json = new JsonObject(); for (KeyValueProto kv : tsKv) { @@ -56,7 +60,14 @@ public class JsonUtils { } else if (value instanceof Long) { return new JsonPrimitive((Long) value); } else if (value instanceof String) { - return JsonParser.parseString((String) value); + try { + return JsonParser.parseString((String) value); + } catch (Exception e) { + if (isBase64(value.toString())) { + value = "\"" + value + "\""; + } + return JsonParser.parseString((String) value); + } } else if (value instanceof Boolean) { return new JsonPrimitive((Boolean) value); } else if (value instanceof Double) { @@ -77,4 +88,7 @@ public class JsonUtils { return jsonObject; } + public static boolean isBase64(String value) { + return value.length() % 4 == 0 && BASE64_PATTERN.matcher(value).matches(); + } } From 381eace2901f59642dd3d17e284a0ab0741c0242 Mon Sep 17 00:00:00 2001 From: nickAS21 Date: Thu, 10 Apr 2025 12:24:43 +0300 Subject: [PATCH 04/16] lwm2m: fix bug for test testSoftwareUpdateByObject9 and testFirmwareUpdateByObject5_Ok --- .../server/ota/DefaultLwM2MOtaUpdateService.java | 3 ++- .../lwm2m/server/ota/LwM2MClientOtaInfo.java | 12 +++++++----- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/DefaultLwM2MOtaUpdateService.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/DefaultLwM2MOtaUpdateService.java index 8ed9c69755..34b5e7c09e 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/DefaultLwM2MOtaUpdateService.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/DefaultLwM2MOtaUpdateService.java @@ -523,7 +523,8 @@ public class DefaultLwM2MOtaUpdateService extends LwM2MExecutorAwareService impl } else { strategy = info.getDeliveryMethod() == FirmwareDeliveryMethod.PULL.code ? LwM2MFirmwareUpdateStrategy.OBJ_5_TEMP_URL : LwM2MFirmwareUpdateStrategy.OBJ_5_BINARY; } - if (clientContext.getProfile(client.getProfileId()).getClientLwM2mSettings().getUseObject19ForOta()){ + Boolean useObject19ForOta = clientContext.getProfile(client.getProfileId()).getClientLwM2mSettings().getUseObject19ForOta(); + if (useObject19ForOta != null && useObject19ForOta){ sendInfoFwToObject19ForOta(client, convertObjectIdToVersionedId(FW_INFO_19_INSTANCE_ID, client), response, otaPackageId); } switch (strategy) { diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/LwM2MClientOtaInfo.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/LwM2MClientOtaInfo.java index d1a8052610..ee1ca92066 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/LwM2MClientOtaInfo.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/LwM2MClientOtaInfo.java @@ -74,16 +74,18 @@ public abstract class LwM2MClientOtaInfo { } else { if (targetPackageId.equals(currentPackageId)) { return false; - } else{ - if (targetTag.equals(currentPackageId)) { + } else if (StringUtils.isNotEmpty(targetTag) && targetTag.equals(currentPackageId)) { + return false; + } else if (StringUtils.isNotEmpty(currentVersion3)) { + if (StringUtils.isNotEmpty(targetTag) && (currentVersion3.contains(targetTag) || targetTag.contains(currentVersion3))) { return false; - } else if (StringUtils.isNotEmpty(currentVersion3)) { - return !(currentVersion3.contains(targetTag) || targetTag.contains(currentVersion3)); } + return !currentVersion3.contains(targetPackageId); + } else { + return true; } } } - return true; } @JsonIgnore From c16e99998d576cb81fa4b34bd7a6090249b371de Mon Sep 17 00:00:00 2001 From: nickAS21 Date: Thu, 10 Apr 2025 17:21:30 +0300 Subject: [PATCH 05/16] lwm2m: refactoring failed to update profile... --- .../lwm2m/server/uplink/DefaultLwM2mUplinkMsgHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/uplink/DefaultLwM2mUplinkMsgHandler.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/uplink/DefaultLwM2mUplinkMsgHandler.java index 0f428ad9af..aa263fbb0d 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/uplink/DefaultLwM2mUplinkMsgHandler.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/uplink/DefaultLwM2mUplinkMsgHandler.java @@ -409,7 +409,7 @@ public class DefaultLwM2mUplinkMsgHandler extends LwM2MExecutorAwareService impl this.onDeviceProfileUpdate(clients, oldProfile, deviceProfile); } } catch (Exception e) { - log.warn("[{}] failed to update profile: {}", deviceProfile.getId(), deviceProfile); + log.warn("[{}] failed to update profile: {} [{}]", deviceProfile.getId(), e.getMessage(), deviceProfile); } } From f722618aa0fd67db1a1f08ec7323550c0b67a43d Mon Sep 17 00:00:00 2001 From: nickAS21 Date: Thu, 10 Apr 2025 17:30:27 +0300 Subject: [PATCH 06/16] lwm2m: refactoring failed to update profile... --- .../lwm2m/server/uplink/DefaultLwM2mUplinkMsgHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/uplink/DefaultLwM2mUplinkMsgHandler.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/uplink/DefaultLwM2mUplinkMsgHandler.java index aa263fbb0d..9976783179 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/uplink/DefaultLwM2mUplinkMsgHandler.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/uplink/DefaultLwM2mUplinkMsgHandler.java @@ -424,7 +424,7 @@ public class DefaultLwM2mUplinkMsgHandler extends LwM2MExecutorAwareService impl this.onDeviceUpdate(client, device, newDeviceProfileOpt); } } catch (Exception e) { - log.warn("[{}] failed to update device: {}", device.getId(), device); + log.warn("[{}] failed to update device: {} [{}]", device.getId(), e.getMessage(), device); } } From ed25c796558bcbe8b831a934bfd45ef9ce2b3396 Mon Sep 17 00:00:00 2001 From: nickAS21 Date: Sat, 12 Apr 2025 14:39:29 +0300 Subject: [PATCH 07/16] lwm2m: add test FW with objectId = 19 --- .../lwm2m/AbstractLwM2MIntegrationTest.java | 11 +++ .../client/LwM2mBinaryAppDataContainer.java | 4 +- .../ota/AbstractOtaLwM2MIntegrationTest.java | 90 ++++++++++++++++++- .../ota/sql/Ota5LwM2MIntegrationTest.java | 59 ++++++++++++ .../ota/DefaultLwM2MOtaUpdateService.java | 10 ++- 5 files changed, 166 insertions(+), 8 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java index 9bfb067bbd..0950d66024 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java @@ -102,6 +102,7 @@ import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClient import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_UPDATE_SUCCESS; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType.NONE; +import static org.thingsboard.server.transport.lwm2m.ota.AbstractOtaLwM2MIntegrationTest.CLIENT_LWM2M_SETTINGS_19; @TestPropertySource(properties = { "transport.lwm2m.enabled=true", @@ -382,6 +383,16 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractTransportInte transportConfiguration.setBootstrap(bootstrapServerCredentials); return transportConfiguration; } + protected Lwm2mDeviceProfileTransportConfiguration getTransportConfiguration19(String observeAttr, List bootstrapServerCredentials) { + Lwm2mDeviceProfileTransportConfiguration transportConfiguration = new Lwm2mDeviceProfileTransportConfiguration(); + TelemetryMappingConfiguration observeAttrConfiguration = JacksonUtil.fromString(observeAttr, TelemetryMappingConfiguration.class); + OtherConfiguration clientLwM2mSettings = JacksonUtil.fromString(CLIENT_LWM2M_SETTINGS_19, OtherConfiguration.class); + transportConfiguration.setBootstrapServerUpdateEnable(true); + transportConfiguration.setObserveAttr(observeAttrConfiguration); + transportConfiguration.setClientLwM2mSettings(clientLwM2mSettings); + transportConfiguration.setBootstrap(bootstrapServerCredentials); + return transportConfiguration; + } protected List getBootstrapServerCredentialsNoSec(LwM2MProfileBootstrapConfigType bootstrapConfigType) { List bootstrap = new ArrayList<>(); diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2mBinaryAppDataContainer.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2mBinaryAppDataContainer.java index 41a2259790..4f12c6d819 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2mBinaryAppDataContainer.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2mBinaryAppDataContainer.java @@ -84,8 +84,8 @@ public class LwM2mBinaryAppDataContainer extends BaseInstanceEnabler implements try { if (id != null) this.setId(id); executorService.scheduleWithFixedDelay(() -> { - fireResourceChange(0); - fireResourceChange(2); +// fireResourceChange(0); +// fireResourceChange(2); } , 1, 1, TimeUnit.SECONDS); // 1 sec // , 1800000, 1800000, TimeUnit.MILLISECONDS); // 30 MIN diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/AbstractOtaLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/AbstractOtaLwM2MIntegrationTest.java index 4d56e891cc..52b3946072 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/AbstractOtaLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/AbstractOtaLwM2MIntegrationTest.java @@ -16,10 +16,14 @@ package org.thingsboard.server.transport.lwm2m.ota; import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.github.dockerjava.zerodep.shaded.org.apache.commons.codec.binary.Hex; import lombok.extern.slf4j.Slf4j; +import org.eclipse.leshan.core.ResponseCode; import org.springframework.mock.web.MockMultipartFile; import org.springframework.test.web.servlet.request.MockMultipartHttpServletRequestBuilder; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.OtaPackageInfo; import org.thingsboard.server.common.data.id.DeviceProfileId; @@ -31,25 +35,29 @@ import org.thingsboard.server.transport.lwm2m.AbstractLwM2MIntegrationTest; import java.util.Comparator; import java.util.List; +import java.util.Optional; import java.util.UUID; import java.util.stream.Collectors; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import static org.thingsboard.rest.client.utils.RestJsonConverter.toTimeseries; import static org.thingsboard.server.common.data.ota.OtaPackageType.FIRMWARE; import static org.thingsboard.server.common.data.ota.OtaPackageType.SOFTWARE; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.RESOURCE_ID_11; +import static org.thingsboard.server.transport.lwm2m.server.ota.DefaultLwM2MOtaUpdateService.*; @Slf4j @DaoSqlTest public abstract class AbstractOtaLwM2MIntegrationTest extends AbstractLwM2MIntegrationTest { - private final String[] RESOURCES_OTA = new String[]{"3.xml", "5.xml", "9.xml"}; + private final String[] RESOURCES_OTA = new String[]{"3.xml", "5.xml", "9.xml", "19.xml"}; protected static final String CLIENT_ENDPOINT_WITHOUT_FW_INFO = "WithoutFirmwareInfoDevice"; protected static final String CLIENT_ENDPOINT_OTA5 = "Ota5_Device"; protected static final String CLIENT_ENDPOINT_OTA9 = "Ota9_Device"; protected List expectedStatuses; - protected final String OBSERVE_ATTRIBUTES_WITH_PARAMS_OTA5 = " {\n" + @@ -78,6 +86,54 @@ public abstract class AbstractOtaLwM2MIntegrationTest extends AbstractLwM2MInteg " \"attributeLwm2m\": {}\n" + " }"; + protected final String OBSERVE_ATTRIBUTES_WITH_PARAMS_OTA5_19 = + + " {\n" + + " \"keyName\": {\n" + + " \"/5_1.2/0/3\": \"state\",\n" + + " \"/5_1.2/0/5\": \"updateResult\",\n" + + " \"/5_1.2/0/6\": \"pkgname\",\n" + + " \"/5_1.2/0/7\": \"pkgversion\",\n" + + " \"/5_1.2/0/9\": \"firmwareUpdateDeliveryMethod\",\n" + + " \"/19_1.1/0/0\": \"dataRead\",\n" + + " \"/19_1.1/65534/0\": \"dataFotaAttr\"\n" + + " },\n" + + " \"observe\": [\n" + + " \"/5_1.2/0/3\",\n" + + " \"/5_1.2/0/5\",\n" + + " \"/5_1.2/0/6\",\n" + + " \"/5_1.2/0/7\",\n" + + " \"/5_1.2/0/9\",\n" + + " \"/19_1.1/0/0\",\n" + + " \"/19_1.1/65534/0\"\n" + + " ],\n" + + " \"attribute\": [],\n" + + " \"telemetry\": [\n" + + " \"/5_1.2/0/3\",\n" + + " \"/5_1.2/0/5\",\n" + + " \"/5_1.2/0/6\",\n" + + " \"/5_1.2/0/7\",\n" + + " \"/5_1.2/0/9\",\n" + + " \"/19_1.1/0/0\",\n" + + " \"/19_1.1/65534/0\"\n" + + " ],\n" + + " \"attributeLwm2m\": {}\n" + + " }"; + + public static final String CLIENT_LWM2M_SETTINGS_19 = + " {\n" + + " \"useObject19ForOta\": true,\n" + + " \"edrxCycle\": null,\n" + + " \"powerMode\": \"DRX\",\n" + + " \"fwUpdateResource\": null,\n" + + " \"fwUpdateStrategy\": 1,\n" + + " \"psmActivityTimer\": null,\n" + + " \"swUpdateResource\": null,\n" + + " \"swUpdateStrategy\": 1,\n" + + " \"pagingTransmissionWindow\": null,\n" + + " \"clientOnlyObserveAfterConnect\": 1\n" + + " }"; + protected final String OBSERVE_ATTRIBUTES_WITH_PARAMS_OTA9 = " {\n" + @@ -159,6 +215,13 @@ public abstract class AbstractOtaLwM2MIntegrationTest extends AbstractLwM2MInteg log.warn("Fetched telemetry by API for deviceId {}, list size {}, tsKvEntries {}", deviceId, tsKvEntries.size(), tsKvEntries); return tsKvEntries; } + protected List getFwSwParamsObject19TelemetryFromAPI(UUID deviceId) throws Exception { + String type_state = "dataFotaAttr"; + final List tsKvEntries = toTimeseries(doGetAsyncTyped("/api/plugins/telemetry/DEVICE/" + deviceId + "/values/timeseries?orderBy=ASC&keys=" + type_state + "&startTs=0&endTs=" + System.currentTimeMillis(), new TypeReference<>() { + })); + log.warn("Fetched telemetry by API for deviceId {}, list size {}, tsKvEntries {}", deviceId, tsKvEntries.size(), tsKvEntries); + return tsKvEntries; + } protected boolean predicateForStatuses(List ts) { List statuses = ts.stream() @@ -169,4 +232,27 @@ public abstract class AbstractOtaLwM2MIntegrationTest extends AbstractLwM2MInteg log.warn("{}", statuses); return statuses.containsAll(expectedStatuses); } + + protected void resultReadOtaParams_19(String resourceIdVer, OtaPackageInfo otaPackageInfo) throws Exception { + String actualResult = sendRPCById(resourceIdVer); + ObjectNode rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class); + assertEquals(ResponseCode.CONTENT.getName(), rpcActualResult.get("result").asText()); + String valStr = rpcActualResult.get("value").asText(); + String start = "{ id=0 value="; + String valHexDec = valStr.substring(valStr.indexOf(start) + start.length(), (valStr.indexOf("}"))); + String valNode = new String(Hex.decodeHex((valHexDec).toCharArray())); + ObjectNode actualResultVal = JacksonUtil.fromString(valNode, ObjectNode.class); + assert actualResultVal != null; + assertEquals(otaPackageInfo.getTitle(), actualResultVal.get(OTA_INFO_19_TITLE).asText()); + assertEquals(otaPackageInfo.getVersion(), actualResultVal.get(OTA_INFO_19_VERSION).asText()); + assertEquals(otaPackageInfo.getChecksum(), actualResultVal.get(OTA_INFO_19_FILE_CHECKSUM256).asText()); + assertEquals(otaPackageInfo.getFileName(), actualResultVal.get(OTA_INFO_19_FILE_NAME).asText()); + assertEquals(Optional.of(otaPackageInfo.getDataSize()), Optional.of((long) actualResultVal.get(OTA_INFO_19_FILE_SIZE).asInt())); + } + + private String sendRPCById(String path) throws Exception { + String setRpcRequest = "{\"method\": \"Read\", \"params\": {\"id\": \"" + path + "\"}}"; + return doPostAsync("/api/plugins/rpc/twoway/" + lwM2MTestClient.getDeviceIdStr(), setRpcRequest, String.class, status().isOk()); + } + } diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/Ota5LwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/Ota5LwM2MIntegrationTest.java index 587eba6aa3..c5d0720042 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/Ota5LwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/Ota5LwM2MIntegrationTest.java @@ -16,17 +16,25 @@ package org.thingsboard.server.transport.lwm2m.ota.sql; import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.github.dockerjava.zerodep.shaded.org.apache.commons.codec.binary.Hex; +import jakarta.validation.constraints.AssertTrue; import lombok.extern.slf4j.Slf4j; +import org.assertj.core.api.Assertions; +import org.eclipse.leshan.core.ResponseCode; import org.junit.Assert; import org.junit.Test; +import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.DeviceProfile; +import org.thingsboard.server.common.data.OtaPackageInfo; import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MDeviceCredentials; import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTransportConfiguration; import org.thingsboard.server.common.data.kv.KvEntry; import org.thingsboard.server.common.data.kv.TsKvEntry; import org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus; import org.thingsboard.server.transport.lwm2m.ota.AbstractOtaLwM2MIntegrationTest; +import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient; import java.util.Arrays; import java.util.Collections; @@ -36,6 +44,9 @@ import java.util.stream.Collectors; import static org.assertj.core.api.Assertions.assertThat; import static org.awaitility.Awaitility.await; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import static org.thingsboard.rest.client.utils.RestJsonConverter.toTimeseries; import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.DOWNLOADED; import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.DOWNLOADING; @@ -44,7 +55,9 @@ import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.INIT import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.QUEUED; import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.UPDATED; import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.UPDATING; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.*; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType.NONE; +import static org.thingsboard.server.transport.lwm2m.server.ota.DefaultLwM2MOtaUpdateService.FW_INSTANCE_ID; @Slf4j public class Ota5LwM2MIntegrationTest extends AbstractOtaLwM2MIntegrationTest { @@ -107,4 +120,50 @@ public class Ota5LwM2MIntegrationTest extends AbstractOtaLwM2MIntegrationTest { } + /** + * ObjectId = 19 + * { + * "title" : "BC68J01", + * "version" : "10", + * "fileChecksumSHA256" : "f2a08d4963e981c78f2a99f62d8439af4437a72ea7267a8c01d013c072c01ded", + * "fileSize" : 59832, + * "fileName" : "FW_BC68JAR01A10_TO_BC68JAR01A09_09.bin", + * "packageType" : "FIRMWARE" + * } + * to base64 + * /5/0/5 -> Update Result (Res); 5/0/3 -> State; + * => ((Res>=0 && Res<=9) && State=0) + * => Write to Package/Write to Package URI -> DOWNLOADING ((Res>=0 && Res<=9) && State=1) + * => Download Finished -> DOWNLOADED ((Res==0 || Res=8) && State=2) + * => Executable resource Update is triggered / Initiate Firmware Update -> UPDATING (Res=0 && State=3) + * => Update Successful [Res==1] + * => Start / Res=0 -> "IDLE" .... + * @throws Exception + */ + @Test + public void testFirmwareUpdateByObject5WithObject19_Ok() throws Exception { + Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration19(OBSERVE_ATTRIBUTES_WITH_PARAMS_OTA5_19, getBootstrapServerCredentialsNoSec(NONE)); + DeviceProfile deviceProfile = createLwm2mDeviceProfile("profileFor" + this.CLIENT_ENDPOINT_OTA5, transportConfiguration); + LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsNoSec(createNoSecClientCredentials(this.CLIENT_ENDPOINT_OTA5)); + final Device device = createLwm2mDevice(deviceCredentials, this.CLIENT_ENDPOINT_OTA5, deviceProfile.getId()); + createNewClient(SECURITY_NO_SEC, null, false, this.CLIENT_ENDPOINT_OTA5, device.getId().getId().toString()); + awaitObserveReadAll(6, device.getId().getId().toString()); + + OtaPackageInfo otaPackageInfo = createFirmware("fw.v.1.5.0-update", deviceProfile.getId()); + device.setFirmwareId(otaPackageInfo.getId()); + final Device savedDevice = doPost("/api/device", device, Device.class); + + assertThat(savedDevice).as("saved device").isNotNull(); + assertThat(getDeviceFromAPI(device.getId().getId())).as("fetched device").isEqualTo(savedDevice); + + expectedStatuses = Arrays.asList(QUEUED, INITIATED, DOWNLOADING, DOWNLOADED, UPDATING, UPDATED); + List ts = await("await on timeseries for FW") + .atMost(TIMEOUT, TimeUnit.SECONDS) + .until(() -> getFwSwStateTelemetryFromAPI(device.getId().getId(), "fw_state"), this::predicateForStatuses); + + String ver_Id_19 = lwM2MTestClient.getLeshanClient().getObjectTree().getModel().getObjectModel(BINARY_APP_DATA_CONTAINER).version; + String resourceIdVer = "/" + BINARY_APP_DATA_CONTAINER + "_" + ver_Id_19 + "/" + FW_INSTANCE_ID + "/" + RESOURCE_ID_0; + resultReadOtaParams_19(resourceIdVer, otaPackageInfo); + log.warn("Object5: Got the ts: {}", ts); + } } diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/DefaultLwM2MOtaUpdateService.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/DefaultLwM2MOtaUpdateService.java index 34b5e7c09e..802d79dd68 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/DefaultLwM2MOtaUpdateService.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/DefaultLwM2MOtaUpdateService.java @@ -108,12 +108,14 @@ public class DefaultLwM2MOtaUpdateService extends LwM2MExecutorAwareService impl public static final String FW_RESULT_ID = "/5/0/5"; public static final String FW_NAME_ID = "/5/0/6"; public static final String FW_VER_ID = "/5/0/7"; - public static final String FW_INFO_19_INSTANCE_ID = "/19/65534"; - public static final String SW_INFO_19_INSTANCE_ID = "/19/65535"; + public static final int FW_INSTANCE_ID = 65534; + public static final String FW_INFO_19_INSTANCE_ID = "/19/" + FW_INSTANCE_ID; + public static final int SW_INSTANCE_ID = 65535; + public static final String SW_INFO_19_INSTANCE_ID = "/19/" + SW_INSTANCE_ID; public static final String OTA_INFO_19_TITLE = "title"; public static final String OTA_INFO_19_VERSION = "version"; - public static final String OTA_INFO_19_FILE_CHECKSUM256 = "fileChecksumSHA256"; - public static final String OTA_INFO_19_FILE_SIZE = "fileSize"; + public static final String OTA_INFO_19_FILE_CHECKSUM256 = "checksum"; + public static final String OTA_INFO_19_FILE_SIZE = "dataSize"; public static final String OTA_INFO_19_FILE_NAME = "fileName"; /** From cf69df895f9264a7c58fbd2a465bef3fc8bdbf1c Mon Sep 17 00:00:00 2001 From: nickAS21 Date: Sun, 13 Apr 2025 14:51:11 +0300 Subject: [PATCH 08/16] lwm2m: refactoring test FW with objectId = 19 --- .../ota/AbstractOtaLwM2MIntegrationTest.java | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/AbstractOtaLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/AbstractOtaLwM2MIntegrationTest.java index 52b3946072..b32ce1a42d 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/AbstractOtaLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/AbstractOtaLwM2MIntegrationTest.java @@ -95,8 +95,7 @@ public abstract class AbstractOtaLwM2MIntegrationTest extends AbstractLwM2MInteg " \"/5_1.2/0/6\": \"pkgname\",\n" + " \"/5_1.2/0/7\": \"pkgversion\",\n" + " \"/5_1.2/0/9\": \"firmwareUpdateDeliveryMethod\",\n" + - " \"/19_1.1/0/0\": \"dataRead\",\n" + - " \"/19_1.1/65534/0\": \"dataFotaAttr\"\n" + + " \"/19_1.1/0/0\": \"dataRead\"\n" + " },\n" + " \"observe\": [\n" + " \"/5_1.2/0/3\",\n" + @@ -104,8 +103,7 @@ public abstract class AbstractOtaLwM2MIntegrationTest extends AbstractLwM2MInteg " \"/5_1.2/0/6\",\n" + " \"/5_1.2/0/7\",\n" + " \"/5_1.2/0/9\",\n" + - " \"/19_1.1/0/0\",\n" + - " \"/19_1.1/65534/0\"\n" + + " \"/19_1.1/0/0\"\n" + " ],\n" + " \"attribute\": [],\n" + " \"telemetry\": [\n" + @@ -114,8 +112,7 @@ public abstract class AbstractOtaLwM2MIntegrationTest extends AbstractLwM2MInteg " \"/5_1.2/0/6\",\n" + " \"/5_1.2/0/7\",\n" + " \"/5_1.2/0/9\",\n" + - " \"/19_1.1/0/0\",\n" + - " \"/19_1.1/65534/0\"\n" + + " \"/19_1.1/0/0\"\n" + " ],\n" + " \"attributeLwm2m\": {}\n" + " }"; @@ -215,13 +212,6 @@ public abstract class AbstractOtaLwM2MIntegrationTest extends AbstractLwM2MInteg log.warn("Fetched telemetry by API for deviceId {}, list size {}, tsKvEntries {}", deviceId, tsKvEntries.size(), tsKvEntries); return tsKvEntries; } - protected List getFwSwParamsObject19TelemetryFromAPI(UUID deviceId) throws Exception { - String type_state = "dataFotaAttr"; - final List tsKvEntries = toTimeseries(doGetAsyncTyped("/api/plugins/telemetry/DEVICE/" + deviceId + "/values/timeseries?orderBy=ASC&keys=" + type_state + "&startTs=0&endTs=" + System.currentTimeMillis(), new TypeReference<>() { - })); - log.warn("Fetched telemetry by API for deviceId {}, list size {}, tsKvEntries {}", deviceId, tsKvEntries.size(), tsKvEntries); - return tsKvEntries; - } protected boolean predicateForStatuses(List ts) { List statuses = ts.stream() From 452699a4fe2fdcaebf821b1614a9e15a688712e2 Mon Sep 17 00:00:00 2001 From: nickAS21 Date: Sun, 13 Apr 2025 15:55:56 +0300 Subject: [PATCH 09/16] lwm2m: add test SW with objectId = 19 --- .../ota/AbstractOtaLwM2MIntegrationTest.java | 32 +++++++++- .../ota/sql/Ota5LwM2MIntegrationTest.java | 13 ++-- .../ota/sql/Ota9LwM2MIntegrationTest.java | 59 +++++++++++++++++-- .../ota/DefaultLwM2MOtaUpdateService.java | 8 ++- 4 files changed, 96 insertions(+), 16 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/AbstractOtaLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/AbstractOtaLwM2MIntegrationTest.java index b32ce1a42d..eb87a9bc3b 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/AbstractOtaLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/AbstractOtaLwM2MIntegrationTest.java @@ -56,6 +56,7 @@ public abstract class AbstractOtaLwM2MIntegrationTest extends AbstractLwM2MInteg protected static final String CLIENT_ENDPOINT_WITHOUT_FW_INFO = "WithoutFirmwareInfoDevice"; protected static final String CLIENT_ENDPOINT_OTA5 = "Ota5_Device"; protected static final String CLIENT_ENDPOINT_OTA9 = "Ota9_Device"; + protected static final String CLIENT_ENDPOINT_OTA9_19 = "Ota9_Device_19"; protected List expectedStatuses; protected final String OBSERVE_ATTRIBUTES_WITH_PARAMS_OTA5 = @@ -155,6 +156,33 @@ public abstract class AbstractOtaLwM2MIntegrationTest extends AbstractLwM2MInteg " ],\n" + " \"attributeLwm2m\": {}\n" + " }"; + protected final String OBSERVE_ATTRIBUTES_WITH_PARAMS_OTA9_19 = + + " {\n" + + " \"keyName\": {\n" + + " \"/9_1.1/0/0\": \"pkgname\",\n" + + " \"/9_1.1/0/1\": \"pkgversion\",\n" + + " \"/9_1.1/0/7\": \"updateState\",\n" + + " \"/9_1.1/0/9\": \"updateResult\",\n" + + " \"/19_1.1/0/0\": \"dataRead\"\n" + + " },\n" + + " \"observe\": [\n" + + " \"/9_1.1/0/0\",\n" + + " \"/9_1.1/0/1\",\n" + + " \"/9_1.1/0/7\",\n" + + " \"/9_1.1/0/9\",\n" + + " \"/19_1.1/0/0\"\n" + + " ],\n" + + " \"attribute\": [],\n" + + " \"telemetry\": [\n" + + " \"/9_1.1/0/0\",\n" + + " \"/9_1.1/0/1\",\n" + + " \"/9_1.1/0/7\",\n" + + " \"/9_1.1/0/9\",\n" + + " \"/19_1.1/0/0\"\n" + + " ],\n" + + " \"attributeLwm2m\": {}\n" + + " }"; public AbstractOtaLwM2MIntegrationTest() { setResources(this.RESOURCES_OTA); @@ -176,14 +204,14 @@ public abstract class AbstractOtaLwM2MIntegrationTest extends AbstractLwM2MInteg return savaData("/api/otaPackage/" + savedFirmwareInfo.getId().getId().toString() + "?checksum={checksum}&checksumAlgorithm={checksumAlgorithm}", testData, CHECKSUM, "SHA256"); } - protected OtaPackageInfo createSoftware(DeviceProfileId deviceProfileId) throws Exception { + protected OtaPackageInfo createSoftware(DeviceProfileId deviceProfileId, String version) throws Exception { String CHECKSUM = "4bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459a"; OtaPackageInfo swInfo = new OtaPackageInfo(); swInfo.setDeviceProfileId(deviceProfileId); swInfo.setType(SOFTWARE); swInfo.setTitle("My sw"); - swInfo.setVersion("v1.0"); + swInfo.setVersion(version); OtaPackageInfo savedFirmwareInfo = doPost("/api/otaPackage", swInfo, OtaPackageInfo.class); diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/Ota5LwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/Ota5LwM2MIntegrationTest.java index c5d0720042..66e0319ab8 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/Ota5LwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/Ota5LwM2MIntegrationTest.java @@ -121,14 +121,13 @@ public class Ota5LwM2MIntegrationTest extends AbstractOtaLwM2MIntegrationTest { /** - * ObjectId = 19 + * ObjectId = 19/65533/0 * { - * "title" : "BC68J01", - * "version" : "10", - * "fileChecksumSHA256" : "f2a08d4963e981c78f2a99f62d8439af4437a72ea7267a8c01d013c072c01ded", - * "fileSize" : 59832, - * "fileName" : "FW_BC68JAR01A10_TO_BC68JAR01A09_09.bin", - * "packageType" : "FIRMWARE" + * "title" : "My firmware", + * "version" : "fw.v.1.5.0-update", + * "checksum" : "4bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459a", + * "fileSize" : 1, + * "fileName" : "filename.txt" * } * to base64 * /5/0/5 -> Update Result (Res); 5/0/3 -> State; diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/Ota9LwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/Ota9LwM2MIntegrationTest.java index 8bb367f66e..24cb905868 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/Ota9LwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/Ota9LwM2MIntegrationTest.java @@ -19,6 +19,7 @@ import lombok.extern.slf4j.Slf4j; import org.junit.Test; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.DeviceProfile; +import org.thingsboard.server.common.data.OtaPackageInfo; import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MDeviceCredentials; import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTransportConfiguration; import org.thingsboard.server.common.data.kv.TsKvEntry; @@ -35,7 +36,11 @@ import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.INIT import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.QUEUED; import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.UPDATED; import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.VERIFIED; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.BINARY_APP_DATA_CONTAINER; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType.NONE; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.RESOURCE_ID_0; +import static org.thingsboard.server.transport.lwm2m.server.ota.DefaultLwM2MOtaUpdateService.FW_INSTANCE_ID; +import static org.thingsboard.server.transport.lwm2m.server.ota.DefaultLwM2MOtaUpdateService.SW_INSTANCE_ID; @Slf4j public class Ota9LwM2MIntegrationTest extends AbstractOtaLwM2MIntegrationTest { @@ -50,14 +55,15 @@ public class Ota9LwM2MIntegrationTest extends AbstractOtaLwM2MIntegrationTest { * */ @Test public void testSoftwareUpdateByObject9() throws Exception { + String clientEndpoint = this.CLIENT_ENDPOINT_OTA9; Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITH_PARAMS_OTA9, getBootstrapServerCredentialsNoSec(NONE)); - DeviceProfile deviceProfile = createLwm2mDeviceProfile("profileFor" + this.CLIENT_ENDPOINT_OTA9, transportConfiguration); - LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsNoSec(createNoSecClientCredentials(this.CLIENT_ENDPOINT_OTA9)); - final Device device = createLwm2mDevice(deviceCredentials, this.CLIENT_ENDPOINT_OTA9, deviceProfile.getId()); - createNewClient(SECURITY_NO_SEC, null, false, this.CLIENT_ENDPOINT_OTA9, device.getId().getId().toString()); + DeviceProfile deviceProfile = createLwm2mDeviceProfile("profileFor" + clientEndpoint, transportConfiguration); + LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsNoSec(createNoSecClientCredentials(clientEndpoint)); + final Device device = createLwm2mDevice(deviceCredentials, clientEndpoint, deviceProfile.getId()); + createNewClient(SECURITY_NO_SEC, null, false, clientEndpoint, device.getId().getId().toString()); awaitObserveReadAll(4, device.getId().getId().toString()); - device.setSoftwareId(createSoftware(deviceProfile.getId()).getId()); + device.setSoftwareId(createSoftware(deviceProfile.getId(), "v1.0").getId()); final Device savedDevice = doPost("/api/device", device, Device.class); //sync call assertThat(savedDevice).as("saved device").isNotNull(); @@ -70,4 +76,47 @@ public class Ota9LwM2MIntegrationTest extends AbstractOtaLwM2MIntegrationTest { .until(() -> getFwSwStateTelemetryFromAPI(device.getId().getId(), "sw_state"), this::predicateForStatuses); log.warn("Object9: Got the ts: {}", ts); } + /** + * ObjectId = 19/65534/0 + * { + * "title" : "My sw", + * "version" : "v1.0.19", + * "checksum" : "4bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459a", + * "fileSize" : 1, + * "fileName" : "filename.txt" + * } + * => Start -> INITIAL (State=0) -> DOWNLOAD STARTED; + * => PKG / URI Write -> DOWNLOAD STARTED (Res=1 (Downloading) && State=1) -> DOWNLOADED + * => PKG Written -> DOWNLOADED (Res=1 Initial && State=2) -> DELIVERED; + * => PKG integrity verified -> DELIVERED (Res=3 (Successfully Downloaded and package integrity verified) && State=3) -> INSTALLED; + * => Install -> INSTALLED (Res=2 SW successfully installed) && State=4) -> Start + * + * */ + @Test + public void testSoftwareUpdateByObject9WithObject19_Ok() throws Exception { + String clientEndpoint = this.CLIENT_ENDPOINT_OTA9_19; + Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration19(OBSERVE_ATTRIBUTES_WITH_PARAMS_OTA9_19, getBootstrapServerCredentialsNoSec(NONE)); + DeviceProfile deviceProfile = createLwm2mDeviceProfile("profileFor" + clientEndpoint, transportConfiguration); + LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsNoSec(createNoSecClientCredentials(clientEndpoint)); + final Device device = createLwm2mDevice(deviceCredentials, clientEndpoint, deviceProfile.getId()); + createNewClient(SECURITY_NO_SEC, null, false, clientEndpoint, device.getId().getId().toString()); + awaitObserveReadAll(5, device.getId().getId().toString()); + OtaPackageInfo otaPackageInfo = createSoftware(deviceProfile.getId(), "v1.0.19"); + device.setSoftwareId(otaPackageInfo.getId()); + final Device savedDevice = doPost("/api/device", device, Device.class); //sync call + + assertThat(savedDevice).as("saved device").isNotNull(); + assertThat(getDeviceFromAPI(device.getId().getId())).as("fetched device").isEqualTo(savedDevice); + + expectedStatuses = List.of( + QUEUED, INITIATED, DOWNLOADING, DOWNLOADING, DOWNLOADING, DOWNLOADED, VERIFIED, UPDATED); + List ts = await("await on timeseries") + .atMost(TIMEOUT, TimeUnit.SECONDS) + .until(() -> getFwSwStateTelemetryFromAPI(device.getId().getId(), "sw_state"), this::predicateForStatuses); + + String ver_Id_19 = lwM2MTestClient.getLeshanClient().getObjectTree().getModel().getObjectModel(BINARY_APP_DATA_CONTAINER).version; + String resourceIdVer = "/" + BINARY_APP_DATA_CONTAINER + "_" + ver_Id_19 + "/" + SW_INSTANCE_ID + "/" + RESOURCE_ID_0; + resultReadOtaParams_19(resourceIdVer, otaPackageInfo); + log.warn("Object9: Got the ts: {}", ts); + } } diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/DefaultLwM2MOtaUpdateService.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/DefaultLwM2MOtaUpdateService.java index 802d79dd68..822d712ac5 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/DefaultLwM2MOtaUpdateService.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/DefaultLwM2MOtaUpdateService.java @@ -108,9 +108,9 @@ public class DefaultLwM2MOtaUpdateService extends LwM2MExecutorAwareService impl public static final String FW_RESULT_ID = "/5/0/5"; public static final String FW_NAME_ID = "/5/0/6"; public static final String FW_VER_ID = "/5/0/7"; - public static final int FW_INSTANCE_ID = 65534; + public static final int FW_INSTANCE_ID = 65533; public static final String FW_INFO_19_INSTANCE_ID = "/19/" + FW_INSTANCE_ID; - public static final int SW_INSTANCE_ID = 65535; + public static final int SW_INSTANCE_ID = 65534; public static final String SW_INFO_19_INSTANCE_ID = "/19/" + SW_INSTANCE_ID; public static final String OTA_INFO_19_TITLE = "title"; public static final String OTA_INFO_19_VERSION = "version"; @@ -551,6 +551,10 @@ public class DefaultLwM2MOtaUpdateService extends LwM2MExecutorAwareService impl if (TransportProtos.ResponseStatus.SUCCESS.equals(response.getResponseStatus())) { UUID otaPackageId = new UUID(response.getOtaPackageIdMSB(), response.getOtaPackageIdLSB()); LwM2MSoftwareUpdateStrategy strategy = info.getStrategy(); + Boolean useObject19ForOta = clientContext.getProfile(client.getProfileId()).getClientLwM2mSettings().getUseObject19ForOta(); + if (useObject19ForOta != null && useObject19ForOta){ + sendInfoFwToObject19ForOta(client, convertObjectIdToVersionedId(SW_INFO_19_INSTANCE_ID, client), response, otaPackageId); + } switch (strategy) { case BINARY: startUpdateUsingBinary(client, convertObjectIdToVersionedId(SW_PACKAGE_ID, client), otaPackageId); From 2561ab6eb1b7f170a9f4842d8087f2fc5466c27c Mon Sep 17 00:00:00 2001 From: nickAS21 Date: Mon, 14 Apr 2025 11:14:46 +0300 Subject: [PATCH 10/16] lwm2m: add fireResourceChange to LwM2mBinaryAppDataContainer --- .../transport/lwm2m/client/LwM2mBinaryAppDataContainer.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2mBinaryAppDataContainer.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2mBinaryAppDataContainer.java index 4f12c6d819..41a2259790 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2mBinaryAppDataContainer.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2mBinaryAppDataContainer.java @@ -84,8 +84,8 @@ public class LwM2mBinaryAppDataContainer extends BaseInstanceEnabler implements try { if (id != null) this.setId(id); executorService.scheduleWithFixedDelay(() -> { -// fireResourceChange(0); -// fireResourceChange(2); + fireResourceChange(0); + fireResourceChange(2); } , 1, 1, TimeUnit.SECONDS); // 1 sec // , 1800000, 1800000, TimeUnit.MILLISECONDS); // 30 MIN From 984040dd4fdc76e89f322ad174818e5820ddfb68 Mon Sep 17 00:00:00 2001 From: nickAS21 Date: Mon, 14 Apr 2025 11:39:25 +0300 Subject: [PATCH 11/16] lwm2m: refactoring import --- .../ota/sql/Ota5LwM2MIntegrationTest.java | 10 ---------- .../ota/sql/Ota9LwM2MIntegrationTest.java | 1 - .../ota/DefaultLwM2MOtaUpdateService.java | 18 ++++++++++-------- 3 files changed, 10 insertions(+), 19 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/Ota5LwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/Ota5LwM2MIntegrationTest.java index 66e0319ab8..b2d95ec906 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/Ota5LwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/Ota5LwM2MIntegrationTest.java @@ -16,15 +16,9 @@ package org.thingsboard.server.transport.lwm2m.ota.sql; import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.node.ObjectNode; -import com.github.dockerjava.zerodep.shaded.org.apache.commons.codec.binary.Hex; -import jakarta.validation.constraints.AssertTrue; import lombok.extern.slf4j.Slf4j; -import org.assertj.core.api.Assertions; -import org.eclipse.leshan.core.ResponseCode; import org.junit.Assert; import org.junit.Test; -import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.DeviceProfile; import org.thingsboard.server.common.data.OtaPackageInfo; @@ -34,7 +28,6 @@ import org.thingsboard.server.common.data.kv.KvEntry; import org.thingsboard.server.common.data.kv.TsKvEntry; import org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus; import org.thingsboard.server.transport.lwm2m.ota.AbstractOtaLwM2MIntegrationTest; -import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient; import java.util.Arrays; import java.util.Collections; @@ -44,9 +37,6 @@ import java.util.stream.Collectors; import static org.assertj.core.api.Assertions.assertThat; import static org.awaitility.Awaitility.await; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import static org.thingsboard.rest.client.utils.RestJsonConverter.toTimeseries; import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.DOWNLOADED; import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.DOWNLOADING; diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/Ota9LwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/Ota9LwM2MIntegrationTest.java index 24cb905868..b2617dd7ba 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/Ota9LwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/Ota9LwM2MIntegrationTest.java @@ -39,7 +39,6 @@ import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.VERI import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.BINARY_APP_DATA_CONTAINER; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType.NONE; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.RESOURCE_ID_0; -import static org.thingsboard.server.transport.lwm2m.server.ota.DefaultLwM2MOtaUpdateService.FW_INSTANCE_ID; import static org.thingsboard.server.transport.lwm2m.server.ota.DefaultLwM2MOtaUpdateService.SW_INSTANCE_ID; @Slf4j diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/DefaultLwM2MOtaUpdateService.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/DefaultLwM2MOtaUpdateService.java index 822d712ac5..92fb2e3853 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/DefaultLwM2MOtaUpdateService.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/DefaultLwM2MOtaUpdateService.java @@ -47,7 +47,11 @@ import org.thingsboard.server.transport.lwm2m.server.attributes.LwM2MAttributesS 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.common.LwM2MExecutorAwareService; -import org.thingsboard.server.transport.lwm2m.server.downlink.*; +import org.thingsboard.server.transport.lwm2m.server.downlink.LwM2mDownlinkMsgHandler; +import org.thingsboard.server.transport.lwm2m.server.downlink.TbLwM2MExecuteCallback; +import org.thingsboard.server.transport.lwm2m.server.downlink.TbLwM2MExecuteRequest; +import org.thingsboard.server.transport.lwm2m.server.downlink.TbLwM2MWriteReplaceRequest; +import org.thingsboard.server.transport.lwm2m.server.downlink.TbLwM2MWriteResponseCallback; import org.thingsboard.server.transport.lwm2m.server.log.LwM2MTelemetryLogService; import org.thingsboard.server.transport.lwm2m.server.ota.firmware.FirmwareDeliveryMethod; import org.thingsboard.server.transport.lwm2m.server.ota.firmware.FirmwareUpdateResult; @@ -118,10 +122,6 @@ public class DefaultLwM2MOtaUpdateService extends LwM2MExecutorAwareService impl public static final String OTA_INFO_19_FILE_SIZE = "dataSize"; public static final String OTA_INFO_19_FILE_NAME = "fileName"; - /** - * Quectel@Hi15RM1-HLB_V1.0@BC68JAR01A10,V150R100C20B300SP7,V150R100C20B300SP7@8 - * Revision:BC68JAR01A10 - */ public static final String FW_3_VER_ID = "/3/0/3"; public static final String FW_DELIVERY_METHOD = "/5/0/9"; @@ -665,11 +665,13 @@ public class DefaultLwM2MOtaUpdateService extends LwM2MExecutorAwareService impl } /** - * send to client: versionedId="/19/65534/0/0, value = FwOtaInfo in bas64 -> format json: + * send to client: versionedId="/19/65533/0/0, value = FwOtaInfo in bas64 -> format json: + * send to client: versionedId="/19/65534/0/0, value = SwOtaInfo in bas64 -> format json: * {"title":"BC68JAR01", * "version":"A10", - * "fileChecksumSHA256":"f2a08d4963e981c78f2a99f62d8439af4437a72ea7267a8c01d013c072c01ded", - * "fileSize":59832} + * "checksum":"f2a08d4963e981c78f2a99f62d8439af4437a72ea7267a8c01d013c072c01ded", + * "fileSize":59832. + * "fileName" : "BC68JAR01A10_TO_BC68JAR01A09_09.bin" } * @param client * @param targetIdVer * @param response From 94be11b45885c77645b5e205f8905a63627262a9 Mon Sep 17 00:00:00 2001 From: nickAS21 Date: Mon, 14 Apr 2025 11:52:54 +0300 Subject: [PATCH 12/16] lwm2m: refactoring import2 --- .../lwm2m/server/ota/DefaultLwM2MOtaUpdateService.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/DefaultLwM2MOtaUpdateService.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/DefaultLwM2MOtaUpdateService.java index 92fb2e3853..2d9d13d830 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/DefaultLwM2MOtaUpdateService.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/DefaultLwM2MOtaUpdateService.java @@ -52,6 +52,8 @@ import org.thingsboard.server.transport.lwm2m.server.downlink.TbLwM2MExecuteCall import org.thingsboard.server.transport.lwm2m.server.downlink.TbLwM2MExecuteRequest; import org.thingsboard.server.transport.lwm2m.server.downlink.TbLwM2MWriteReplaceRequest; import org.thingsboard.server.transport.lwm2m.server.downlink.TbLwM2MWriteResponseCallback; +import org.thingsboard.server.transport.lwm2m.server.downlink.TbLwM2MCreateRequest; +import org.thingsboard.server.transport.lwm2m.server.downlink.TbLwM2MCreateResponseCallback; import org.thingsboard.server.transport.lwm2m.server.log.LwM2MTelemetryLogService; import org.thingsboard.server.transport.lwm2m.server.ota.firmware.FirmwareDeliveryMethod; import org.thingsboard.server.transport.lwm2m.server.ota.firmware.FirmwareUpdateResult; From fea2d7e4a37343e517619a4c5cb1e67dc598ce32 Mon Sep 17 00:00:00 2001 From: nickAS21 Date: Tue, 15 Apr 2025 15:04:17 +0300 Subject: [PATCH 13/16] lwm2m: refactoring SW with unInstall (argument is 1) -> "ForUpdate" --- .../ota/DefaultLwM2MOtaUpdateService.java | 69 ++++++++++--------- .../ota/firmware/LwM2MClientFwOtaInfo.java | 9 ++- .../ota/software/LwM2MClientSwOtaInfo.java | 11 ++- .../lwm2m/utils/LwM2mValueConverterImpl.java | 10 +-- 4 files changed, 60 insertions(+), 39 deletions(-) diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/DefaultLwM2MOtaUpdateService.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/DefaultLwM2MOtaUpdateService.java index 2d9d13d830..cfa8feb89f 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/DefaultLwM2MOtaUpdateService.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/DefaultLwM2MOtaUpdateService.java @@ -114,15 +114,6 @@ public class DefaultLwM2MOtaUpdateService extends LwM2MExecutorAwareService impl public static final String FW_RESULT_ID = "/5/0/5"; public static final String FW_NAME_ID = "/5/0/6"; public static final String FW_VER_ID = "/5/0/7"; - public static final int FW_INSTANCE_ID = 65533; - public static final String FW_INFO_19_INSTANCE_ID = "/19/" + FW_INSTANCE_ID; - public static final int SW_INSTANCE_ID = 65534; - public static final String SW_INFO_19_INSTANCE_ID = "/19/" + SW_INSTANCE_ID; - public static final String OTA_INFO_19_TITLE = "title"; - public static final String OTA_INFO_19_VERSION = "version"; - public static final String OTA_INFO_19_FILE_CHECKSUM256 = "checksum"; - public static final String OTA_INFO_19_FILE_SIZE = "dataSize"; - public static final String OTA_INFO_19_FILE_NAME = "fileName"; public static final String FW_3_VER_ID = "/3/0/3"; public static final String FW_DELIVERY_METHOD = "/5/0/9"; @@ -138,6 +129,16 @@ public class DefaultLwM2MOtaUpdateService extends LwM2MExecutorAwareService impl public static final String SW_RESULT_ID = "/9/0/9"; public static final String SW_UN_INSTALL_ID = "/9/0/6"; + public static final int FW_INSTANCE_ID = 65533; + public static final String FW_INFO_19_INSTANCE_ID = "/19/" + FW_INSTANCE_ID; + public static final int SW_INSTANCE_ID = 65534; + public static final String SW_INFO_19_INSTANCE_ID = "/19/" + SW_INSTANCE_ID; + public static final String OTA_INFO_19_TITLE = "title"; + public static final String OTA_INFO_19_VERSION = "version"; + public static final String OTA_INFO_19_FILE_CHECKSUM256 = "checksum"; + public static final String OTA_INFO_19_FILE_SIZE = "dataSize"; + public static final String OTA_INFO_19_FILE_NAME = "fileName"; + private final Map fwStates = new ConcurrentHashMap<>(); private final Map swStates = new ConcurrentHashMap<>(); @@ -529,7 +530,7 @@ public class DefaultLwM2MOtaUpdateService extends LwM2MExecutorAwareService impl } Boolean useObject19ForOta = clientContext.getProfile(client.getProfileId()).getClientLwM2mSettings().getUseObject19ForOta(); if (useObject19ForOta != null && useObject19ForOta){ - sendInfoFwToObject19ForOta(client, convertObjectIdToVersionedId(FW_INFO_19_INSTANCE_ID, client), response, otaPackageId); + sendInfoToObject19ForOta(client, FW_INFO_19_INSTANCE_ID, response, otaPackageId); } switch (strategy) { case OBJ_5_BINARY: @@ -555,7 +556,7 @@ public class DefaultLwM2MOtaUpdateService extends LwM2MExecutorAwareService impl LwM2MSoftwareUpdateStrategy strategy = info.getStrategy(); Boolean useObject19ForOta = clientContext.getProfile(client.getProfileId()).getClientLwM2mSettings().getUseObject19ForOta(); if (useObject19ForOta != null && useObject19ForOta){ - sendInfoFwToObject19ForOta(client, convertObjectIdToVersionedId(SW_INFO_19_INSTANCE_ID, client), response, otaPackageId); + sendInfoToObject19ForOta(client, SW_INFO_19_INSTANCE_ID, response, otaPackageId); } switch (strategy) { case BINARY: @@ -591,21 +592,24 @@ public class DefaultLwM2MOtaUpdateService extends LwM2MExecutorAwareService impl } private void executeFwUpdate(LwM2mClient client) { + log.trace("[{}] Execute SW [{}]", client.getEndpoint(), FW_EXECUTE_ID); String fwExecuteVerId = convertObjectIdToVersionedId(FW_EXECUTE_ID, client); TbLwM2MExecuteRequest request = TbLwM2MExecuteRequest.builder().versionedId(fwExecuteVerId).timeout(clientContext.getRequestTimeout(client)).build(); downlinkHandler.sendExecuteRequest(client, request, new TbLwM2MExecuteCallback(logService, client, fwExecuteVerId)); } private void executeSwInstall(LwM2mClient client) { + log.trace("[{}] Execute SW (install) [{}]", client.getEndpoint(), SW_INSTALL_ID); String swInstallVerId = convertObjectIdToVersionedId(SW_INSTALL_ID, client); TbLwM2MExecuteRequest request = TbLwM2MExecuteRequest.builder().versionedId(swInstallVerId).timeout(clientContext.getRequestTimeout(client)).build(); downlinkHandler.sendExecuteRequest(client, request, new TbLwM2MExecuteCallback(logService, client, swInstallVerId)); } private void executeSwUninstallForUpdate(LwM2mClient client) { - String swInInstallVerId = convertObjectIdToVersionedId(SW_UN_INSTALL_ID, client); - TbLwM2MExecuteRequest request = TbLwM2MExecuteRequest.builder().versionedId(swInInstallVerId).params("1").timeout(clientContext.getRequestTimeout(client)).build(); - downlinkHandler.sendExecuteRequest(client, request, new TbLwM2MExecuteCallback(logService, client, swInInstallVerId)); + log.trace("[{}] Execute SW (uninstall with params(\"1\") ) [{}]", client.getEndpoint(), SW_UN_INSTALL_ID); + String swUnInstallVerId = convertObjectIdToVersionedId(SW_UN_INSTALL_ID, client); + TbLwM2MExecuteRequest request = TbLwM2MExecuteRequest.builder().versionedId(swUnInstallVerId).params("1").timeout(clientContext.getRequestTimeout(client)).build(); + downlinkHandler.sendExecuteRequest(client, request, new TbLwM2MExecuteCallback(logService, client, swUnInstallVerId)); } private Optional getAttributeValue(List attrs, String keyName) { @@ -675,36 +679,37 @@ public class DefaultLwM2MOtaUpdateService extends LwM2MExecutorAwareService impl * "fileSize":59832. * "fileName" : "BC68JAR01A10_TO_BC68JAR01A09_09.bin" } * @param client - * @param targetIdVer + * @param targetId * @param response * @param otaPackageId */ - private void sendInfoFwToObject19ForOta(LwM2mClient client, String targetIdVer, TransportProtos.GetOtaPackageResponseMsg response, UUID otaPackageId) { - log.trace("[{}] Current info fw toObject19ForOta", client.getEndpoint()); + private void sendInfoToObject19ForOta(LwM2mClient client, String targetId, TransportProtos.GetOtaPackageResponseMsg response, UUID otaPackageId) { + log.trace("[{}] Current info ota toObject19ForOta [{}]", client.getEndpoint(), targetId); + String targetIdVer = convertObjectIdToVersionedId(targetId, client); ObjectModel objectModel = client.getObjectModel(targetIdVer, modelProvider); if (objectModel != null) { try { if (client.getRegistration().getSupportedObject().get(19) != null) { - ObjectNode objectNodeInfoFw = JacksonUtil.newObjectNode(); + ObjectNode objectNodeInfoOta = JacksonUtil.newObjectNode(); byte[] firmwareChunk = otaPackageDataCache.get(otaPackageId.toString(), 0, 0); String fileChecksumSHA256 = Hashing.sha256().hashBytes(firmwareChunk).toString(); - objectNodeInfoFw.put(OTA_INFO_19_TITLE, response.getTitle()); - objectNodeInfoFw.put(OTA_INFO_19_VERSION, response.getVersion()); - objectNodeInfoFw.put(OTA_INFO_19_FILE_CHECKSUM256, fileChecksumSHA256); - objectNodeInfoFw.put(OTA_INFO_19_FILE_SIZE, firmwareChunk.length); - objectNodeInfoFw.put(OTA_INFO_19_FILE_NAME, response.getFileName()); - String objectNodeInfoFwStr = JacksonUtil.toString(objectNodeInfoFw); - assert objectNodeInfoFwStr != null; - String objectNodeInfoFwBase64 = Base64.getEncoder().encodeToString(objectNodeInfoFwStr.getBytes()); + objectNodeInfoOta.put(OTA_INFO_19_TITLE, response.getTitle()); + objectNodeInfoOta.put(OTA_INFO_19_VERSION, response.getVersion()); + objectNodeInfoOta.put(OTA_INFO_19_FILE_CHECKSUM256, fileChecksumSHA256); + objectNodeInfoOta.put(OTA_INFO_19_FILE_SIZE, firmwareChunk.length); + objectNodeInfoOta.put(OTA_INFO_19_FILE_NAME, response.getFileName()); + String objectNodeInfoOtaStr = JacksonUtil.toString(objectNodeInfoOta); + assert objectNodeInfoOtaStr != null; + String objectNodeInfoOtaBase64 = Base64.getEncoder().encodeToString(objectNodeInfoOtaStr.getBytes()); - LwM2mPath pathFwInstance = new LwM2mPath(FW_INFO_19_INSTANCE_ID); - if (client.getRegistration().getAvailableInstances().contains(pathFwInstance)) { + LwM2mPath pathOtaInstance = new LwM2mPath(targetId); + if (client.getRegistration().getAvailableInstances().contains(pathOtaInstance)) { String versionId = targetIdVer + "/0/0"; - TbLwM2MWriteReplaceRequest request = TbLwM2MWriteReplaceRequest.builder().versionedId(versionId).value(objectNodeInfoFwBase64).timeout(clientContext.getRequestTimeout(client)).build(); + TbLwM2MWriteReplaceRequest request = TbLwM2MWriteReplaceRequest.builder().versionedId(versionId).value(objectNodeInfoOtaBase64).timeout(clientContext.getRequestTimeout(client)).build(); downlinkHandler.sendWriteReplaceRequest(client, request, new TbLwM2MWriteResponseCallback(uplinkHandler, logService, client, versionId)); } else { - String valueResourcesStr = "{\"" + 0 + "\":{\"0\":\"" + objectNodeInfoFwBase64 + "\"}}"; + String valueResourcesStr = "{\"" + 0 + "\":{\"0\":\"" + objectNodeInfoOtaBase64 + "\"}}"; String valueStr = "{\"id\":\"" + targetIdVer + "\",\"value\":" + valueResourcesStr + "}"; RpcCreateRequest requestBody = JacksonUtil.fromString(valueStr, RpcCreateRequest.class); assert requestBody != null; @@ -713,8 +718,8 @@ public class DefaultLwM2MOtaUpdateService extends LwM2MExecutorAwareService impl downlinkHandler.sendCreateRequest(client, builder.build(), new TbLwM2MCreateResponseCallback(uplinkHandler, logService, client, targetIdVer)); } } else { - String errorMsg = "Failed to send Info Fw to object 19. The client does not have object 19."; - log.trace("[{}] {}", client.getEndpoint(), errorMsg); + String errorMsg = String.format("[%s], Failed to send Info Ota to objectInstance [%s]. The client does not have object 19.", client.getEndpoint(), targetId); + log.trace(errorMsg); logService.log(client, errorMsg); } } catch (Exception e){ diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/firmware/LwM2MClientFwOtaInfo.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/firmware/LwM2MClientFwOtaInfo.java index 6f6aae9c45..0ef082e740 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/firmware/LwM2MClientFwOtaInfo.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/firmware/LwM2MClientFwOtaInfo.java @@ -23,6 +23,9 @@ import lombok.ToString; import org.thingsboard.server.common.data.ota.OtaPackageType; import org.thingsboard.server.transport.lwm2m.server.ota.LwM2MClientOtaInfo; +import static org.thingsboard.server.transport.lwm2m.server.ota.firmware.FirmwareUpdateResult.UPDATE_SUCCESSFULLY; + + @Data @EqualsAndHashCode(callSuper = true) @NoArgsConstructor @@ -43,6 +46,11 @@ public class LwM2MClientFwOtaInfo extends LwM2MClientOtaInfo UPDATE_SUCCESSFULLY.getCode()) { + failedPackageId = getPackageId(targetName, targetVersion); + } + switch (result) { case INITIAL: break; @@ -50,7 +58,6 @@ public class LwM2MClientFwOtaInfo extends LwM2MClientOtaInfo= NOT_ENOUGH_STORAGE.getCode()) { + failedPackageId = getPackageId(targetName, targetVersion); + } switch (result) { case INITIAL: break; - //TODO: implement + case SUCCESSFULLY_INSTALLED: + retryAttempts = 0; + break; default: - failedPackageId = getPackageId(targetName, targetVersion); break; } } diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/utils/LwM2mValueConverterImpl.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/utils/LwM2mValueConverterImpl.java index 480f4ed778..91d55305da 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/utils/LwM2mValueConverterImpl.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/utils/LwM2mValueConverterImpl.java @@ -31,6 +31,7 @@ import java.text.SimpleDateFormat; import java.util.Base64; import java.util.Date; +import static org.eclipse.leshan.core.model.ResourceModel.Type.NONE; import static org.eclipse.leshan.core.model.ResourceModel.Type.OPAQUE; @Slf4j @@ -53,14 +54,15 @@ public class LwM2mValueConverterImpl implements LwM2mValueConverter { return value; } - if (currentType == expectedType) { - /** expected type */ - return value; - } if (currentType == null) { currentType = OPAQUE; } + if (currentType == expectedType || currentType == NONE) { + /** expected type */ + return value; + } + switch (expectedType) { case INTEGER: switch (currentType) { From 33ec93c32dc0ddcb5fe1ec60a36763494ce8ac30 Mon Sep 17 00:00:00 2001 From: nickAS21 Date: Fri, 18 Apr 2025 12:31:15 +0300 Subject: [PATCH 14/16] lwm2m: comments1 --- .../lwm2m/ota/sql/Ota5LwM2MIntegrationTest.java | 3 ++- .../server/downlink/DefaultLwM2mDownlinkMsgHandler.java | 2 +- .../server/common/transport/util/JsonUtils.java | 9 +-------- 3 files changed, 4 insertions(+), 10 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/Ota5LwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/Ota5LwM2MIntegrationTest.java index b2d95ec906..3065255687 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/Ota5LwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/Ota5LwM2MIntegrationTest.java @@ -45,8 +45,9 @@ import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.INIT import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.QUEUED; import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.UPDATED; import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.UPDATING; -import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.*; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.BINARY_APP_DATA_CONTAINER; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType.NONE; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.RESOURCE_ID_0; import static org.thingsboard.server.transport.lwm2m.server.ota.DefaultLwM2MOtaUpdateService.FW_INSTANCE_ID; @Slf4j diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/DefaultLwM2mDownlinkMsgHandler.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/DefaultLwM2mDownlinkMsgHandler.java index ed685dfc6c..787db56411 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/DefaultLwM2mDownlinkMsgHandler.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/DefaultLwM2mDownlinkMsgHandler.java @@ -99,6 +99,7 @@ import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Collectors; +import static org.apache.commons.codec.binary.Base64.isBase64; import static org.eclipse.leshan.core.link.lwm2m.attributes.LwM2mAttributes.DIMENSION; import static org.eclipse.leshan.core.link.lwm2m.attributes.LwM2mAttributes.ENABLER_VERSION; import static org.eclipse.leshan.core.link.lwm2m.attributes.LwM2mAttributes.EVALUATE_MAXIMUM_PERIOD; @@ -113,7 +114,6 @@ import static org.eclipse.leshan.core.link.lwm2m.attributes.LwM2mAttributes.SHOR import static org.eclipse.leshan.core.link.lwm2m.attributes.LwM2mAttributes.STEP; import static org.eclipse.leshan.core.model.ResourceModel.Type.OBJLNK; import static org.eclipse.leshan.core.model.ResourceModel.Type.OPAQUE; -import static org.thingsboard.server.common.transport.util.JsonUtils.isBase64; import static org.thingsboard.server.transport.lwm2m.utils.LwM2MTransportUtil.convertMultiResourceValuesFromRpcBody; import static org.thingsboard.server.transport.lwm2m.utils.LwM2MTransportUtil.createModelsDefault; import static org.thingsboard.server.transport.lwm2m.utils.LwM2MTransportUtil.fromVersionedIdToObjectId; diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/util/JsonUtils.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/util/JsonUtils.java index a79d897daf..cdbc371c60 100644 --- a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/util/JsonUtils.java +++ b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/util/JsonUtils.java @@ -23,13 +23,10 @@ import org.thingsboard.server.gen.transport.TransportProtos.KeyValueProto; import java.util.List; import java.util.Map; -import java.util.regex.Pattern; +import static org.apache.commons.codec.binary.Base64.isBase64; public class JsonUtils { - private static final Pattern BASE64_PATTERN = - Pattern.compile("^[A-Za-z0-9+/]+={0,2}$"); - public static JsonObject getJsonObject(List tsKv) { JsonObject json = new JsonObject(); for (KeyValueProto kv : tsKv) { @@ -87,8 +84,4 @@ public class JsonUtils { return jsonObject; } - - public static boolean isBase64(String value) { - return value.length() % 4 == 0 && BASE64_PATTERN.matcher(value).matches(); - } } From d8435246dde65ddffa1f065bf3b7d8a1f56fff9e Mon Sep 17 00:00:00 2001 From: nickAS21 Date: Fri, 18 Apr 2025 19:24:45 +0300 Subject: [PATCH 15/16] lwm2m: add Base64 from java.util and add Test FW to objectId=19 jsonNode --- .../rpc/sql/RpcLwm2mIntegrationWriteTest.java | 65 ++++++++++++++++--- .../DefaultLwM2mDownlinkMsgHandler.java | 2 +- .../ota/DefaultLwM2MOtaUpdateService.java | 2 - .../common/transport/util/JsonUtils.java | 9 ++- 4 files changed, 65 insertions(+), 13 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationWriteTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationWriteTest.java index 9d64e1a64d..01030c24bd 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationWriteTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationWriteTest.java @@ -16,26 +16,22 @@ package org.thingsboard.server.transport.lwm2m.rpc.sql; import com.fasterxml.jackson.databind.node.ObjectNode; +import com.google.common.hash.Hashing; +import org.eclipse.leshan.client.resource.LwM2mObjectEnabler; import org.eclipse.leshan.core.ResponseCode; import org.eclipse.leshan.core.node.LwM2mPath; import org.junit.Test; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.script.api.tbel.TbUtils; import org.thingsboard.server.transport.lwm2m.rpc.AbstractRpcLwM2MIntegrationTest; +import java.util.Base64; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.OBJECT_INSTANCE_ID_0; -import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.OBJECT_INSTANCE_ID_1; -import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.OBJECT_INSTANCE_ID_2; -import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.RESOURCE_ID_0; -import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.RESOURCE_ID_14; -import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.RESOURCE_ID_15; -import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.RESOURCE_ID_9; -import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.RESOURCE_ID_NAME_3_14; -import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.RESOURCE_INSTANCE_ID_2; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.*; +import static org.thingsboard.server.transport.lwm2m.server.ota.DefaultLwM2MOtaUpdateService.*; public class RpcLwm2mIntegrationWriteTest extends AbstractRpcLwM2MIntegrationTest { @@ -77,6 +73,28 @@ public class RpcLwm2mIntegrationWriteTest extends AbstractRpcLwM2MIntegrationTes String expected = "LwM2mSingleResource [id=" + RESOURCE_ID_14 + ", value=" + expectedValue + ", type=STRING]"; assertTrue(actualValues.contains(expected)); } + + @Test + public void testWriteReplaceValueMultipleResource_Result_CHANGED_Multi_Instance_Resource_must_One_ValueJsonNodeToBase64() throws Exception { + LwM2mObjectEnabler lwM2mObjectEnabler = lwM2MTestClient.getLeshanClient().getObjectTree().getObjectEnabler(BINARY_APP_DATA_CONTAINER); + if (lwM2mObjectEnabler != null) { + String expectedPath = objectIdVer_19 + "/" + FW_INSTANCE_ID + "/"; + String expectedValueStr = getJsonNodeBase64(); + String expectedValue = "{\"" + RESOURCE_ID_0 + "\":{\"0\":\"" + expectedValueStr + "\"}}"; + String actualResult = sendRPCreateById(expectedPath, expectedValue); + ObjectNode rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class); + assertEquals(ResponseCode.CREATED.getName(), rpcActualResult.get("result").asText()); + actualResult = sendRPCReadById(expectedPath); + rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class); + String actualValues = rpcActualResult.get("value").asText(); + byte[] expectedValue0 = TbUtils.base64ToBytes(expectedValueStr); + String expectedInstance = "LwM2mObjectInstance [id=" + FW_INSTANCE_ID; + assertTrue(actualValues.contains(expectedInstance)); + String expected = "{0=LwM2mMultipleResource [id=0, values={0=LwM2mResourceInstance [id=0, value=" + expectedValue0.length + "Bytes, type=OPAQUE]}"; + assertTrue(actualValues.contains(expected)); + } + } + @Test public void testWriteReplaceValueMultipleResource_Result_CHANGED_Multi_Instance_Resource_must_One() throws Exception { int resourceInstanceId0 = 0; @@ -525,4 +543,33 @@ public class RpcLwm2mIntegrationWriteTest extends AbstractRpcLwM2MIntegrationTes String setRpcRequest = "{\"method\": \"WriteComposite\", \"params\": {\"nodes\":" + nodes + "}}"; return doPostAsync("/api/plugins/rpc/twoway/" + lwM2MTestClient.getDeviceIdStr(), setRpcRequest, String.class, status().isOk()); } + + /** + * ObjectId = 19/65533/0 + * { + * "title" : "My firmware", + * "version" : "fw.v.1.5.0-update", + * "checksum" : "4bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459a", + * "fileSize" : 1, + * "fileName" : "filename.txt" + * } + */ + private String getJsonNodeBase64() { + ObjectNode objectNodeInfoOta = JacksonUtil.newObjectNode(); + byte[] firmwareChunk = new byte[]{1}; + String fileChecksumSHA256 = Hashing.sha256().hashBytes(firmwareChunk).toString(); + objectNodeInfoOta.put(OTA_INFO_19_TITLE, "My firmware"); + objectNodeInfoOta.put(OTA_INFO_19_VERSION, "fw.v.1.5.0-update"); + objectNodeInfoOta.put(OTA_INFO_19_FILE_CHECKSUM256, fileChecksumSHA256); + objectNodeInfoOta.put(OTA_INFO_19_FILE_SIZE, firmwareChunk.length); + objectNodeInfoOta.put(OTA_INFO_19_FILE_NAME, "filename.txt"); + String objectNodeInfoOtaStr = JacksonUtil.toString(objectNodeInfoOta); + assert objectNodeInfoOtaStr != null; + return Base64.getEncoder().encodeToString(objectNodeInfoOtaStr.getBytes()); + } + + private String sendRPCreateById(String path, String value) throws Exception { + String setRpcRequest = "{\"method\": \"Create\", \"params\": {\"id\": \"" + path + "\", \"value\": " + value + " }}"; + return doPostAsync("/api/plugins/rpc/twoway/" + lwM2MTestClient.getDeviceIdStr(), setRpcRequest, String.class, status().isOk()); + } } diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/DefaultLwM2mDownlinkMsgHandler.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/DefaultLwM2mDownlinkMsgHandler.java index 787db56411..ed685dfc6c 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/DefaultLwM2mDownlinkMsgHandler.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/DefaultLwM2mDownlinkMsgHandler.java @@ -99,7 +99,6 @@ import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Collectors; -import static org.apache.commons.codec.binary.Base64.isBase64; import static org.eclipse.leshan.core.link.lwm2m.attributes.LwM2mAttributes.DIMENSION; import static org.eclipse.leshan.core.link.lwm2m.attributes.LwM2mAttributes.ENABLER_VERSION; import static org.eclipse.leshan.core.link.lwm2m.attributes.LwM2mAttributes.EVALUATE_MAXIMUM_PERIOD; @@ -114,6 +113,7 @@ import static org.eclipse.leshan.core.link.lwm2m.attributes.LwM2mAttributes.SHOR import static org.eclipse.leshan.core.link.lwm2m.attributes.LwM2mAttributes.STEP; import static org.eclipse.leshan.core.model.ResourceModel.Type.OBJLNK; import static org.eclipse.leshan.core.model.ResourceModel.Type.OPAQUE; +import static org.thingsboard.server.common.transport.util.JsonUtils.isBase64; import static org.thingsboard.server.transport.lwm2m.utils.LwM2MTransportUtil.convertMultiResourceValuesFromRpcBody; import static org.thingsboard.server.transport.lwm2m.utils.LwM2MTransportUtil.createModelsDefault; import static org.thingsboard.server.transport.lwm2m.utils.LwM2MTransportUtil.fromVersionedIdToObjectId; diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/DefaultLwM2MOtaUpdateService.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/DefaultLwM2MOtaUpdateService.java index cfa8feb89f..da94c19422 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/DefaultLwM2MOtaUpdateService.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/DefaultLwM2MOtaUpdateService.java @@ -701,8 +701,6 @@ public class DefaultLwM2MOtaUpdateService extends LwM2MExecutorAwareService impl String objectNodeInfoOtaStr = JacksonUtil.toString(objectNodeInfoOta); assert objectNodeInfoOtaStr != null; String objectNodeInfoOtaBase64 = Base64.getEncoder().encodeToString(objectNodeInfoOtaStr.getBytes()); - - LwM2mPath pathOtaInstance = new LwM2mPath(targetId); if (client.getRegistration().getAvailableInstances().contains(pathOtaInstance)) { String versionId = targetIdVer + "/0/0"; diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/util/JsonUtils.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/util/JsonUtils.java index cdbc371c60..a79d897daf 100644 --- a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/util/JsonUtils.java +++ b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/util/JsonUtils.java @@ -23,10 +23,13 @@ import org.thingsboard.server.gen.transport.TransportProtos.KeyValueProto; import java.util.List; import java.util.Map; -import static org.apache.commons.codec.binary.Base64.isBase64; +import java.util.regex.Pattern; public class JsonUtils { + private static final Pattern BASE64_PATTERN = + Pattern.compile("^[A-Za-z0-9+/]+={0,2}$"); + public static JsonObject getJsonObject(List tsKv) { JsonObject json = new JsonObject(); for (KeyValueProto kv : tsKv) { @@ -84,4 +87,8 @@ public class JsonUtils { return jsonObject; } + + public static boolean isBase64(String value) { + return value.length() % 4 == 0 && BASE64_PATTERN.matcher(value).matches(); + } } From 841d3ea33ff47294ca52ff50bfd334b7fafdc2d1 Mon Sep 17 00:00:00 2001 From: nickAS21 Date: Thu, 24 Apr 2025 15:56:58 +0300 Subject: [PATCH 16/16] lwm2m: update with master --- .../transport/lwm2m/AbstractLwM2MIntegrationTest.java | 1 + .../data/device/profile/lwm2m/OtherConfiguration.java | 2 +- .../lwm2m/server/ota/DefaultLwM2MOtaUpdateService.java | 8 ++++---- ui-ngx/src/assets/locale/locale.constant-en_US.json | 4 ++-- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java index 0950d66024..827112cf2a 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java @@ -383,6 +383,7 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractTransportInte transportConfiguration.setBootstrap(bootstrapServerCredentials); return transportConfiguration; } + protected Lwm2mDeviceProfileTransportConfiguration getTransportConfiguration19(String observeAttr, List bootstrapServerCredentials) { Lwm2mDeviceProfileTransportConfiguration transportConfiguration = new Lwm2mDeviceProfileTransportConfiguration(); TelemetryMappingConfiguration observeAttrConfiguration = JacksonUtil.fromString(observeAttr, TelemetryMappingConfiguration.class); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/OtherConfiguration.java b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/OtherConfiguration.java index 0d59ef6f8f..b056309634 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/OtherConfiguration.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/OtherConfiguration.java @@ -30,7 +30,7 @@ import org.thingsboard.server.common.data.device.data.PowerSavingConfiguration; @JsonIgnoreProperties(ignoreUnknown = true) public class OtherConfiguration extends PowerSavingConfiguration { - private Boolean useObject19ForOta; + private Boolean useObject19ForOtaInfo; private Integer fwUpdateStrategy; private Integer swUpdateStrategy; private Integer clientOnlyObserveAfterConnect; diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/DefaultLwM2MOtaUpdateService.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/DefaultLwM2MOtaUpdateService.java index da94c19422..ea8c2acb14 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/DefaultLwM2MOtaUpdateService.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/DefaultLwM2MOtaUpdateService.java @@ -528,8 +528,8 @@ public class DefaultLwM2MOtaUpdateService extends LwM2MExecutorAwareService impl } else { strategy = info.getDeliveryMethod() == FirmwareDeliveryMethod.PULL.code ? LwM2MFirmwareUpdateStrategy.OBJ_5_TEMP_URL : LwM2MFirmwareUpdateStrategy.OBJ_5_BINARY; } - Boolean useObject19ForOta = clientContext.getProfile(client.getProfileId()).getClientLwM2mSettings().getUseObject19ForOta(); - if (useObject19ForOta != null && useObject19ForOta){ + Boolean useObject19ForOtaInfo = clientContext.getProfile(client.getProfileId()).getClientLwM2mSettings().getUseObject19ForOtaInfo(); + if (useObject19ForOtaInfo != null && useObject19ForOtaInfo){ sendInfoToObject19ForOta(client, FW_INFO_19_INSTANCE_ID, response, otaPackageId); } switch (strategy) { @@ -554,8 +554,8 @@ public class DefaultLwM2MOtaUpdateService extends LwM2MExecutorAwareService impl if (TransportProtos.ResponseStatus.SUCCESS.equals(response.getResponseStatus())) { UUID otaPackageId = new UUID(response.getOtaPackageIdMSB(), response.getOtaPackageIdLSB()); LwM2MSoftwareUpdateStrategy strategy = info.getStrategy(); - Boolean useObject19ForOta = clientContext.getProfile(client.getProfileId()).getClientLwM2mSettings().getUseObject19ForOta(); - if (useObject19ForOta != null && useObject19ForOta){ + Boolean useObject19ForOtaInfo = clientContext.getProfile(client.getProfileId()).getClientLwM2mSettings().getUseObject19ForOtaInfo(); + if (useObject19ForOtaInfo != null && useObject19ForOtaInfo){ sendInfoToObject19ForOta(client, SW_INFO_19_INSTANCE_ID, response, otaPackageId); } switch (strategy) { diff --git a/ui-ngx/src/assets/locale/locale.constant-en_US.json b/ui-ngx/src/assets/locale/locale.constant-en_US.json index a7f231bdb2..b160a44b0e 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -2175,8 +2175,8 @@ "no-config-servers": "No servers configured", "others-tab": "Other settings", "ota-update": "OTA update", - "use-object-19-for-ota-update": "Use Object 19 for OTA update", - "use-object-19-for-ota-update-hint": "Use Resource ObjectId = 19 for OTA updates: FirmWare → InstanceId = 65534, SoftWare → InstanceId = 65535. The data format is JSON wrapped in Base64. The main field in JSON: \"Checksum\" (SHA256). Additional fields: \"Title\" (OTA name), \"Version\" (OTA version), \"File Name\" (file name for storing OTA on the client), \"File Size\" (OTA size in bytes).", + "use-object-19-for-ota-update": "Use Object 19 for OTA file metadata (checksum, size, version, name)", + "use-object-19-for-ota-update-hint": "Use Resource ObjectId = 19 for OTA updates: FirmWare → InstanceId = 65534, SoftWare → InstanceId = 65535. The data format is JSON wrapped in Base64. This JSON contains OTA file metadata (file info): \"Checksum\" (SHA256). Additional fields: \"Title\" (OTA name), \"Version\" (OTA version), \"File Name\" (file name for storing OTA on the client), \"File Size\" (OTA size in bytes).", "client-strategy": "Client strategy when connecting", "client-strategy-label": "Strategy", "client-strategy-only-observe": "Only Observe Request to the client after the initial connection",