diff --git a/application/src/main/java/org/thingsboard/server/service/firmware/DefaultFirmwareStateService.java b/application/src/main/java/org/thingsboard/server/service/firmware/DefaultFirmwareStateService.java index ca369b3698..ed9f8a9eaf 100644 --- a/application/src/main/java/org/thingsboard/server/service/firmware/DefaultFirmwareStateService.java +++ b/application/src/main/java/org/thingsboard/server/service/firmware/DefaultFirmwareStateService.java @@ -24,8 +24,9 @@ import org.thingsboard.server.common.data.DataConstants; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.DeviceProfile; import org.thingsboard.server.common.data.FirmwareInfo; -import org.thingsboard.server.common.data.firmware.FirmwareUtil; import org.thingsboard.server.common.data.firmware.FirmwareType; +import org.thingsboard.server.common.data.firmware.FirmwareUpdateStatus; +import org.thingsboard.server.common.data.firmware.FirmwareUtil; import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.id.FirmwareId; import org.thingsboard.server.common.data.id.TenantId; @@ -66,11 +67,11 @@ import static org.thingsboard.server.common.data.firmware.FirmwareKey.STATE; import static org.thingsboard.server.common.data.firmware.FirmwareKey.TITLE; import static org.thingsboard.server.common.data.firmware.FirmwareKey.TS; import static org.thingsboard.server.common.data.firmware.FirmwareKey.VERSION; +import static org.thingsboard.server.common.data.firmware.FirmwareType.FIRMWARE; +import static org.thingsboard.server.common.data.firmware.FirmwareType.SOFTWARE; import static org.thingsboard.server.common.data.firmware.FirmwareUtil.getAttributeKey; import static org.thingsboard.server.common.data.firmware.FirmwareUtil.getTargetTelemetryKey; import static org.thingsboard.server.common.data.firmware.FirmwareUtil.getTelemetryKey; -import static org.thingsboard.server.common.data.firmware.FirmwareType.FIRMWARE; -import static org.thingsboard.server.common.data.firmware.FirmwareType.SOFTWARE; @Slf4j @Service diff --git a/application/src/main/java/org/thingsboard/server/service/resource/DefaultTbResourceService.java b/application/src/main/java/org/thingsboard/server/service/resource/DefaultTbResourceService.java index 63c587405a..15ca6d7be3 100644 --- a/application/src/main/java/org/thingsboard/server/service/resource/DefaultTbResourceService.java +++ b/application/src/main/java/org/thingsboard/server/service/resource/DefaultTbResourceService.java @@ -44,6 +44,7 @@ import java.util.Base64; import java.util.Comparator; import java.util.List; import java.util.stream.Collectors; +import java.util.stream.Stream; import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_KEY; import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_SEARCH_TEXT; @@ -130,7 +131,7 @@ public class DefaultTbResourceService implements TbResourceService { List resources = resourceService.findTenantResourcesByResourceTypeAndObjectIds(tenantId, ResourceType.LWM2M_MODEL, objectIds); return resources.stream() - .map(this::toLwM2mObject) + .flatMap(s -> Stream.ofNullable(toLwM2mObject(s))) .sorted(getComparator(sortProperty, sortOrder)) .collect(Collectors.toList()); } @@ -141,7 +142,7 @@ public class DefaultTbResourceService implements TbResourceService { validateId(tenantId, INCORRECT_TENANT_ID + tenantId); PageData resourcePageData = resourceService.findTenantResourcesByResourceTypeAndPageLink(tenantId, ResourceType.LWM2M_MODEL, pageLink); return resourcePageData.getData().stream() - .map(this::toLwM2mObject) + .flatMap(s -> Stream.ofNullable(toLwM2mObject(s))) .sorted(getComparator(sortProperty, sortOrder)) .collect(Collectors.toList()); } @@ -190,9 +191,14 @@ public class DefaultTbResourceService implements TbResourceService { resources.add(lwM2MResourceObserve); } }); - instance.setResources(resources.toArray(LwM2mResourceObserve[]::new)); - lwM2mObject.setInstances(new LwM2mInstance[]{instance}); - return lwM2mObject; + if (resources.size() > 0) { + instance.setResources(resources.toArray(LwM2mResourceObserve[]::new)); + lwM2mObject.setInstances(new LwM2mInstance[]{instance}); + return lwM2mObject; + } + else { + return null; + } } } catch (IOException | InvalidDDFFileException e) { log.error("Could not parse the XML of objectModel with name [{}]", resource.getSearchText(), e); diff --git a/application/src/main/resources/thingsboard.yml b/application/src/main/resources/thingsboard.yml index d14adc0573..1cc89feab2 100644 --- a/application/src/main/resources/thingsboard.yml +++ b/application/src/main/resources/thingsboard.yml @@ -672,6 +672,8 @@ transport: recommended_supported_groups: "${LWM2M_RECOMMENDED_SUPPORTED_GROUPS:true}" response_pool_size: "${LWM2M_RESPONSE_POOL_SIZE:100}" registered_pool_size: "${LWM2M_REGISTERED_POOL_SIZE:10}" + registration_store_pool_size: "${LWM2M_REGISTRATION_STORE_POOL_SIZE:100}" + clean_period_in_sec: "${LWM2M_CLEAN_PERIOD_IN_SEC:2}" update_registered_pool_size: "${LWM2M_UPDATE_REGISTERED_POOL_SIZE:10}" un_registered_pool_size: "${LWM2M_UN_REGISTERED_POOL_SIZE:10}" log_max_length: "${LWM2M_LOG_MAX_LENGTH:100}" diff --git a/application/src/test/java/org/thingsboard/server/service/resource/BaseTbResourceServiceTest.java b/application/src/test/java/org/thingsboard/server/service/resource/BaseTbResourceServiceTest.java index ffdefc27ed..464ca5c3cf 100644 --- a/application/src/test/java/org/thingsboard/server/service/resource/BaseTbResourceServiceTest.java +++ b/application/src/test/java/org/thingsboard/server/service/resource/BaseTbResourceServiceTest.java @@ -32,7 +32,6 @@ import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.security.Authority; import org.thingsboard.server.controller.AbstractControllerTest; import org.thingsboard.server.dao.exception.DataValidationException; -import org.thingsboard.server.dao.service.AbstractServiceTest; import org.thingsboard.server.dao.service.DaoSqlTest; import java.util.ArrayList; @@ -57,7 +56,7 @@ public class BaseTbResourceServiceTest extends AbstractControllerTest { "\n" + "\n" + "LWM2M\n" + - "\n" + + "RW\n" + "Single\n" + "Mandatory\n" + "String\n" + diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/DataConstants.java b/common/data/src/main/java/org/thingsboard/server/common/data/DataConstants.java index f4b5fef1f9..62459fc0ad 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/DataConstants.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/DataConstants.java @@ -92,26 +92,6 @@ public class DataConstants { public static final String CLIENT_ID = "clientId"; public static final String USERNAME = "username"; public static final String PASSWORD = "password"; - -//<<<<<<< HEAD -//======= -// //firmware -// //telemetry -// public static final String CURRENT_FIRMWARE_TITLE = "current_fw_title"; -// public static final String CURRENT_FIRMWARE_VERSION = "current_fw_version"; -// public static final String TARGET_FIRMWARE_TITLE = "target_fw_title"; -// public static final String TARGET_FIRMWARE_VERSION = "target_fw_version"; -// public static final String TARGET_FIRMWARE_TS = "target_fw_ts"; -// public static final String FIRMWARE_STATE = "fw_state"; -// -// //attributes -// //telemetry -// public static final String FIRMWARE_TITLE = "fw_title"; -// public static final String FIRMWARE_VERSION = "fw_version"; -// public static final String FIRMWARE_SIZE = "fw_size"; -// public static final String FIRMWARE_CHECKSUM = "fw_checksum"; -// public static final String FIRMWARE_CHECKSUM_ALGORITHM = "fw_checksum_algorithm"; -//>>>>>>> origin/master public static final String EDGE_MSG_SOURCE = "edge"; public static final String MSG_SOURCE_KEY = "source"; diff --git a/application/src/main/java/org/thingsboard/server/service/firmware/FirmwareUpdateStatus.java b/common/data/src/main/java/org/thingsboard/server/common/data/firmware/FirmwareUpdateStatus.java similarity index 93% rename from application/src/main/java/org/thingsboard/server/service/firmware/FirmwareUpdateStatus.java rename to common/data/src/main/java/org/thingsboard/server/common/data/firmware/FirmwareUpdateStatus.java index ffaab79caf..3e46174792 100644 --- a/application/src/main/java/org/thingsboard/server/service/firmware/FirmwareUpdateStatus.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/firmware/FirmwareUpdateStatus.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.thingsboard.server.service.firmware; +package org.thingsboard.server.common.data.firmware; public enum FirmwareUpdateStatus { QUEUED, INITIATED, DOWNLOADING, DOWNLOADED, VERIFIED, UPDATING, UPDATED, FAILED diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/config/LwM2MTransportServerConfig.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/config/LwM2MTransportServerConfig.java index cd8287da4c..683420e66b 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/config/LwM2MTransportServerConfig.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/config/LwM2MTransportServerConfig.java @@ -64,6 +64,14 @@ public class LwM2MTransportServerConfig implements LwM2MSecureServerConfig { @Value("${transport.lwm2m.registered_pool_size:}") private int registeredPoolSize; + @Getter + @Value("${transport.lwm2m.registration_store_pool_size:}") + private int registrationStorePoolSize; + + @Getter + @Value("${transport.lwm2m.clean_period_in_sec:}") + private int cleanPeriodInSec; + @Getter @Value("${transport.lwm2m.update_registered_pool_size:}") private int updateRegisteredPoolSize; diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2MTransportMsgHandler.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2MTransportMsgHandler.java index a654abdad5..71cc2f11ee 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2MTransportMsgHandler.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2MTransportMsgHandler.java @@ -44,6 +44,7 @@ import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.DeviceProfile; import org.thingsboard.server.common.data.firmware.FirmwareKey; import org.thingsboard.server.common.data.firmware.FirmwareType; +import org.thingsboard.server.common.data.firmware.FirmwareUpdateStatus; import org.thingsboard.server.common.data.firmware.FirmwareUtil; import org.thingsboard.server.common.data.id.FirmwareId; import org.thingsboard.server.common.transport.TransportService; @@ -84,19 +85,21 @@ import java.util.stream.Collectors; import static org.eclipse.californium.core.coap.CoAP.ResponseCode.BAD_REQUEST; import static org.eclipse.leshan.core.attributes.Attribute.OBJECT_VERSION; -import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_KEY; import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_PATH; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportServerHelper.getValueFromKvProto; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.CLIENT_NOT_AUTHORIZED; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.DEVICE_ATTRIBUTES_REQUEST; -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FR_OBJECT_ID; -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FR_PATH_RESOURCE_VER_ID; +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.EqualsFwSateToFirmwareUpdateStatus; +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_ID; +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_RESULT_ID; +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_STATE_ID; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_ERROR; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_INFO; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_VALUE; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LWM2M_STRATEGY_2; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.DISCOVER; +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.DISCOVER_All; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.EXECUTE; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.OBSERVE; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.OBSERVE_CANCEL; @@ -105,6 +108,7 @@ import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.L import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.WRITE_ATTRIBUTES; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.WRITE_REPLACE; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.WRITE_UPDATE; +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SW_ID; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertJsonArrayToSet; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertPathFromIdVerToObjectId; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertPathFromObjectIdToIdVer; @@ -124,12 +128,12 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler private final TransportService transportService; private final LwM2mTransportContext context; - private final LwM2MTransportServerConfig config; - private final FirmwareDataCache firmwareDataCache; - private final LwM2mTransportServerHelper helper; + public final LwM2MTransportServerConfig config; + public final FirmwareDataCache firmwareDataCache; + public final LwM2mTransportServerHelper helper; private final LwM2MJsonAdaptor adaptor; private final LwM2mClientContext clientContext; - private final LwM2mTransportRequest lwM2mTransportRequest; + public final LwM2mTransportRequest lwM2mTransportRequest; public DefaultLwM2MTransportMsgHandler(TransportService transportService, LwM2MTransportServerConfig config, LwM2mTransportServerHelper helper, LwM2mClientContext clientContext, @@ -182,6 +186,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler transportService.process(sessionInfo, TransportProtos.SubscribeToAttributeUpdatesMsg.newBuilder().build(), null); transportService.process(sessionInfo, TransportProtos.SubscribeToRPCMsg.newBuilder().build(), null); this.getInfoFirmwareUpdate(lwM2MClient); + this.getInfoSoftwareUpdate(lwM2MClient); this.initLwM2mFromClientValue(registration, lwM2MClient); this.sendLogsToThingsboard(LOG_LW2M_INFO + ": Client create after Registration", registration.getId()); } else { @@ -327,9 +332,16 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler String pathName = tsKvProto.getKv().getKey(); String pathIdVer = this.getPresentPathIntoProfile(sessionInfo, pathName); Object valueNew = getValueFromKvProto(tsKvProto.getKv()); - //TODO: react on change of the firmware name. - if (FirmwareUtil.getAttributeKey(FirmwareType.FIRMWARE, FirmwareKey.VERSION).equals(pathName) && !valueNew.equals(lwM2MClient.getFrUpdate().getCurrentFwVersion())) { + if ((FirmwareUtil.getAttributeKey(FirmwareType.FIRMWARE, FirmwareKey.VERSION).equals(pathName) + && (!valueNew.equals(lwM2MClient.getFwUpdate().getCurrentVersion()))) + || (FirmwareUtil.getAttributeKey(FirmwareType.FIRMWARE, FirmwareKey.TITLE).equals(pathName) + && (!valueNew.equals(lwM2MClient.getFwUpdate().getCurrentTitle())))) { this.getInfoFirmwareUpdate(lwM2MClient); + } else if ((FirmwareUtil.getAttributeKey(FirmwareType.SOFTWARE, FirmwareKey.VERSION).equals(pathName) + && (!valueNew.equals(lwM2MClient.getSwUpdate().getCurrentVersion()))) + || (FirmwareUtil.getAttributeKey(FirmwareType.SOFTWARE, FirmwareKey.TITLE).equals(pathName) + && (!valueNew.equals(lwM2MClient.getSwUpdate().getCurrentTitle())))) { + this.getInfoSoftwareUpdate(lwM2MClient); } if (pathIdVer != null) { ResourceModel resourceModel = lwM2MClient.getResourceModel(pathIdVer, this.config @@ -354,8 +366,8 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler msg.getSharedUpdatedList().forEach(tsKvProto -> { String pathName = tsKvProto.getKv().getKey(); Object valueNew = getValueFromKvProto(tsKvProto.getKv()); - if (FirmwareUtil.getAttributeKey(FirmwareType.FIRMWARE, FirmwareKey.VERSION).equals(pathName) && !valueNew.equals(lwM2MClient.getFrUpdate().getCurrentFwVersion())) { - lwM2MClient.getFrUpdate().setCurrentFwVersion((String) valueNew); + if (FirmwareUtil.getAttributeKey(FirmwareType.FIRMWARE, FirmwareKey.VERSION).equals(pathName) && !valueNew.equals(lwM2MClient.getFwUpdate().getCurrentVersion())) { + lwM2MClient.getFwUpdate().setCurrentVersion((String) valueNew); } }); log.info("[{}] delete [{}] onAttributeUpdate", msg.getSharedDeletedList(), sessionInfo); @@ -460,22 +472,22 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler .getAsJsonObject().toString(), new TypeToken>() { }.getType()); if (WRITE_UPDATE == lwm2mClientRpcRequest.getTypeOper()) { - ConcurrentHashMap paramsResourceId = convertParamsToResourceId (params, sessionInfo); + ConcurrentHashMap paramsResourceId = convertParamsToResourceId(params, sessionInfo); if (paramsResourceId.size() > 0) { lwm2mClientRpcRequest.setParams(paramsResourceId); } - } - else { + } else { lwm2mClientRpcRequest.setParams(params); } - } - else if (rpcRequest.has(lwm2mClientRpcRequest.paramsKey) && rpcRequest.get(lwm2mClientRpcRequest.paramsKey).isJsonArray()) { + } else if (rpcRequest.has(lwm2mClientRpcRequest.paramsKey) && rpcRequest.get(lwm2mClientRpcRequest.paramsKey).isJsonArray()) { new Gson().fromJson(rpcRequest.get(lwm2mClientRpcRequest.paramsKey) .getAsJsonObject().toString(), new TypeToken>() { }.getType()); } lwm2mClientRpcRequest.setSessionInfo(sessionInfo); - if (OBSERVE_READ_ALL != lwm2mClientRpcRequest.getTypeOper() && lwm2mClientRpcRequest.getTargetIdVer() == null) { + if (!(OBSERVE_READ_ALL == lwm2mClientRpcRequest.getTypeOper() + || DISCOVER_All == lwm2mClientRpcRequest.getTypeOper()) + && lwm2mClientRpcRequest.getTargetIdVer() == null) { lwm2mClientRpcRequest.setErrorMsg(lwm2mClientRpcRequest.targetIdVerKey + " and " + lwm2mClientRpcRequest.keyNameKey + " is null or bad format"); } @@ -499,12 +511,12 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler return lwm2mClientRpcRequest; } - private ConcurrentHashMap convertParamsToResourceId (ConcurrentHashMap params, - SessionInfoProto sessionInfo) { + private ConcurrentHashMap convertParamsToResourceId(ConcurrentHashMap params, + SessionInfoProto sessionInfo) { ConcurrentHashMap paramsIdVer = new ConcurrentHashMap<>(); params.forEach((k, v) -> { String targetIdVer = this.getPresentPathIntoProfile(sessionInfo, k); - if (targetIdVer != null ) { + if (targetIdVer != null) { LwM2mPath targetId = new LwM2mPath(convertPathFromIdVerToObjectId(targetIdVer)); if (targetId.isResource()) { paramsIdVer.put(String.valueOf(targetId.getResourceId()), v); @@ -640,7 +652,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler /** * @param registration - * @param lwM2mObject - - * @param pathIdVer - + * @param pathIdVer - */ private void updateObjectResourceValue(Registration registration, LwM2mObject lwM2mObject, String pathIdVer) { LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(pathIdVer)); @@ -678,18 +690,31 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler LwM2mClient lwM2MClient = clientContext.getOrRegister(registration); if (lwM2MClient.saveResourceValue(path, lwM2mResource, this.config .getModelProvider())) { - if (FR_PATH_RESOURCE_VER_ID.equals(convertPathFromIdVerToObjectId(path)) && - lwM2MClient.getFrUpdate().getCurrentFwVersion() != null - && !lwM2MClient.getFrUpdate().getCurrentFwVersion().equals(lwM2MClient.getFrUpdate().getClientFwVersion()) - && lwM2MClient.isUpdateFw()) { + /** version != null + * set setClient_fw_info... = value + **/ + if (lwM2MClient.getFwUpdate().isInfoFwSwUpdate()) { + lwM2MClient.getFwUpdate().initReadValue(this, path); + } + if (lwM2MClient.getSwUpdate().isInfoFwSwUpdate()) { + lwM2MClient.getSwUpdate().initReadValue(this, path); + } + if (lwM2MClient.getFwUpdate().getStateUpdate() != null + && !FirmwareUpdateStatus.DOWNLOADING.name().equals(lwM2MClient.getFwUpdate().getStateUpdate()) + && (convertPathFromObjectIdToIdVer(FW_STATE_ID, registration).equals(path) + || convertPathFromObjectIdToIdVer(FW_RESULT_ID, registration).equals(path))) { + Long stateFw = (Long) lwM2MClient.getResourceValue(null, FW_STATE_ID); + Long updateResultFw = (Long) lwM2MClient.getResourceValue(null, FW_RESULT_ID); + FirmwareUpdateStatus state = EqualsFwSateToFirmwareUpdateStatus(LwM2mTransportUtil.StateFw.fromStateFwByCode(stateFw.intValue()), + LwM2mTransportUtil.UpdateResultFw.fromUpdateResultFwByCode(updateResultFw.intValue())); + if (state != FirmwareUpdateStatus.DOWNLOADING && state != FirmwareUpdateStatus.DOWNLOADED) { + lwM2MClient.getFwUpdate().setStateUpdate(state.name()); + lwM2MClient.getFwUpdate().sendLogs(OBSERVE.name()); + } + log.warn ("update Resource [{}]", lwM2mResource); + } + if (FirmwareUpdateStatus.DOWNLOADED.name().equals(lwM2MClient.getSwUpdate().getStateUpdate())) { - /** version != null - * set setClient_fw_version = value - **/ - lwM2MClient.setUpdateFw(false); - lwM2MClient.getFrUpdate().setClientFwVersion(lwM2mResource.getValue().toString()); - log.warn("updateFirmwareClient3"); - this.updateFirmwareClient(lwM2MClient); } Set paths = new HashSet<>(); paths.add(path); @@ -845,7 +870,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler Object finalvalueKvProto = valueKvProto; Gson gson = new GsonBuilder().create(); resourceValue.getValues().forEach((k, v) -> { - Object val = this.converter.convertValue(resourceValue.getValue(), currentType, expectedType, + Object val = this.converter.convertValue(v, currentType, expectedType, new LwM2mPath(convertPathFromIdVerToObjectId(pathIdVer))); JsonElement element = gson.toJsonTree(val, val.getClass()); ((JsonObject) finalvalueKvProto).add(String.valueOf(k), element); @@ -937,7 +962,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler */ private void onDeviceProfileUpdate(Set registrationIds, DeviceProfile deviceProfile) { LwM2mClientProfile lwM2MClientProfileOld = clientContext.getProfiles().get(deviceProfile.getUuidId()).clone(); - if (clientContext.toClientProfile(deviceProfile) != null) { + if (clientContext.profileUpdate(deviceProfile) != null) { // #1 JsonArray attributeOld = lwM2MClientProfileOld.getPostAttributeProfile(); Set attributeSetOld = convertJsonArrayToSet(attributeOld); @@ -947,7 +972,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler JsonObject keyNameOld = lwM2MClientProfileOld.getPostKeyNameProfile(); JsonObject attributeLwm2mOld = lwM2MClientProfileOld.getPostAttributeLwm2mProfile(); - LwM2mClientProfile lwM2MClientProfileNew = clientContext.getProfiles().get(deviceProfile.getUuidId()); + LwM2mClientProfile lwM2MClientProfileNew = clientContext.getProfiles().get(deviceProfile.getUuidId()).clone(); JsonArray attributeNew = lwM2MClientProfileNew.getPostAttributeProfile(); Set attributeSetNew = convertJsonArrayToSet(attributeNew); JsonArray telemetryNew = lwM2MClientProfileNew.getPostTelemetryProfile(); @@ -996,7 +1021,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler Registration registration = clientContext.getRegistration(registrationId); this.readObserveFromProfile(registration, sendAttrToThingsboard.getPathPostParametersAdd(), READ); // send attr/telemetry to tingsboard for new path - this.updateAttrTelemetry(registration, sendAttrToThingsboard.getPathPostParametersAdd()); +// this.updateAttrTelemetry(registration, sendAttrToThingsboard.getPathPostParametersAdd()); }); } // #4.2 del @@ -1275,7 +1300,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler * @param registration - Registration LwM2M Client * @return - sessionInfo after access connect client */ - private SessionInfoProto getSessionInfoOrCloseSession(Registration registration) { + public SessionInfoProto getSessionInfoOrCloseSession(Registration registration) { return getSessionInfoOrCloseSession(clientContext.getOrRegister(registration)); } @@ -1331,62 +1356,72 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler } public void getInfoFirmwareUpdate(LwM2mClient lwM2MClient) { - SessionInfoProto sessionInfo = this.getSessionInfoOrCloseSession(lwM2MClient); - if (sessionInfo != null) { - TransportProtos.GetFirmwareRequestMsg getFirmwareRequestMsg = TransportProtos.GetFirmwareRequestMsg.newBuilder() - .setDeviceIdMSB(sessionInfo.getDeviceIdMSB()) - .setDeviceIdLSB(sessionInfo.getDeviceIdLSB()) - .setTenantIdMSB(sessionInfo.getTenantIdMSB()) - .setTenantIdLSB(sessionInfo.getTenantIdLSB()) - .setType(FirmwareType.FIRMWARE.name()) - .build(); - transportService.process(sessionInfo, getFirmwareRequestMsg, - new TransportServiceCallback<>() { - @Override - public void onSuccess(TransportProtos.GetFirmwareResponseMsg response) { - if (TransportProtos.ResponseStatus.SUCCESS.equals(response.getResponseStatus())) { - lwM2MClient.getFrUpdate().setCurrentFwVersion(response.getVersion()); - lwM2MClient.getFrUpdate().setCurrentFwId(new FirmwareId(new UUID(response.getFirmwareIdMSB(), response.getFirmwareIdLSB())).getId()); - lwM2MClient.setUpdateFw(true); - readRequestToClientFirmwareVer(lwM2MClient.getRegistration()); - } else { - log.trace("Firmware [{}] [{}]", lwM2MClient.getDeviceName(), response.getResponseStatus().toString()); + if (lwM2MClient.getRegistration().getSupportedVersion(FW_ID) != null) { + SessionInfoProto sessionInfo = this.getSessionInfoOrCloseSession(lwM2MClient); + if (sessionInfo != null) { + DefaultLwM2MTransportMsgHandler serviceImpl = this; + transportService.process(sessionInfo, createFirmwareRequestMsg(sessionInfo, FirmwareType.FIRMWARE.name()), + new TransportServiceCallback<>() { + @Override + public void onSuccess(TransportProtos.GetFirmwareResponseMsg response) { + if (TransportProtos.ResponseStatus.SUCCESS.equals(response.getResponseStatus()) + && response.getType().equals(FirmwareType.FIRMWARE.name())) { + lwM2MClient.getFwUpdate().setCurrentVersion(response.getVersion()); + lwM2MClient.getFwUpdate().setCurrentTitle(response.getTitle()); + lwM2MClient.getFwUpdate().setCurrentId(new FirmwareId(new UUID(response.getFirmwareIdMSB(), response.getFirmwareIdLSB())).getId()); + lwM2MClient.getFwUpdate().sendReadInfo(serviceImpl); + } else { + log.trace("Firmware [{}] [{}]", lwM2MClient.getDeviceName(), response.getResponseStatus().toString()); + } } - } - @Override - public void onError(Throwable e) { - log.trace("Failed to process credentials ", e); - } - }); + @Override + public void onError(Throwable e) { + log.warn("Failed to process firmwareUpdate ", e); + } + }); + } } } - /** - * @param registration - */ - public void readRequestToClientFirmwareVer(Registration registration) { - String pathIdVer = convertPathFromObjectIdToIdVer(FR_PATH_RESOURCE_VER_ID, registration); - lwM2mTransportRequest.sendAllRequest(registration, pathIdVer, READ, ContentFormat.TLV.getName(), - null, config.getTimeout(), null); - } + public void getInfoSoftwareUpdate(LwM2mClient lwM2MClient) { + if (lwM2MClient.getRegistration().getSupportedVersion(SW_ID) != null) { + SessionInfoProto sessionInfo = this.getSessionInfoOrCloseSession(lwM2MClient); + if (sessionInfo != null) { + DefaultLwM2MTransportMsgHandler serviceImpl = this; + transportService.process(sessionInfo, createFirmwareRequestMsg(sessionInfo, FirmwareType.SOFTWARE.name()), + new TransportServiceCallback<>() { + @Override + public void onSuccess(TransportProtos.GetFirmwareResponseMsg response) { + if (TransportProtos.ResponseStatus.SUCCESS.equals(response.getResponseStatus()) + && response.getType().equals(FirmwareType.SOFTWARE.name())) { + lwM2MClient.getSwUpdate().setCurrentVersion(response.getVersion()); + lwM2MClient.getSwUpdate().setCurrentTitle(response.getTitle()); + lwM2MClient.getSwUpdate().setCurrentId(new FirmwareId(new UUID(response.getFirmwareIdMSB(), response.getFirmwareIdLSB())).getId()); + lwM2MClient.getSwUpdate().sendReadInfo(serviceImpl); + } else { + log.trace("Software [{}] [{}]", lwM2MClient.getDeviceName(), response.getResponseStatus().toString()); + } + } - /** - * @param lwM2MClient - - */ - public void updateFirmwareClient(LwM2mClient lwM2MClient) { - if (!lwM2MClient.getFrUpdate().getCurrentFwVersion().equals(lwM2MClient.getFrUpdate().getClientFwVersion())) { - int chunkSize = 0; - int chunk = 0; - byte[] firmwareChunk = firmwareDataCache.get(lwM2MClient.getFrUpdate().getCurrentFwId().toString(), chunkSize, chunk); - String verSupportedObject = lwM2MClient.getRegistration().getSupportedObject().get(FR_OBJECT_ID); - String targetIdVer = LWM2M_SEPARATOR_PATH + FR_OBJECT_ID + LWM2M_SEPARATOR_KEY + verSupportedObject + LWM2M_SEPARATOR_PATH + 0 + LWM2M_SEPARATOR_PATH + 0; - lwM2mTransportRequest.sendAllRequest(lwM2MClient.getRegistration(), targetIdVer, WRITE_REPLACE, ContentFormat.OPAQUE.getName(), - firmwareChunk, config.getTimeout(), null); - log.warn("updateFirmwareClient [{}] [{}]", lwM2MClient.getFrUpdate().getCurrentFwVersion(), lwM2MClient.getFrUpdate().getClientFwVersion()); + @Override + public void onError(Throwable e) { + log.trace("Failed to process softwareUpdate ", e); + } + }); + } } } + private TransportProtos.GetFirmwareRequestMsg createFirmwareRequestMsg(SessionInfoProto sessionInfo, String nameFwSW) { + return TransportProtos.GetFirmwareRequestMsg.newBuilder() + .setDeviceIdMSB(sessionInfo.getDeviceIdMSB()) + .setDeviceIdLSB(sessionInfo.getDeviceIdLSB()) + .setTenantIdMSB(sessionInfo.getTenantIdMSB()) + .setTenantIdLSB(sessionInfo.getTenantIdLSB()) + .setType(nameFwSW) + .build(); + } /** * !!! sharedAttr === profileAttr !!! diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2mTransportService.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2mTransportService.java index 3df1263a3f..ed7242ad0d 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2mTransportService.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2mTransportService.java @@ -24,11 +24,13 @@ import org.eclipse.leshan.core.util.Hex; import org.eclipse.leshan.server.californium.LeshanServer; import org.eclipse.leshan.server.californium.LeshanServerBuilder; import org.eclipse.leshan.server.californium.registration.CaliforniumRegistrationStore; +import org.eclipse.leshan.server.californium.registration.InMemoryRegistrationStore; import org.eclipse.leshan.server.model.LwM2mModelProvider; import org.eclipse.leshan.server.security.DefaultAuthorizer; import org.eclipse.leshan.server.security.EditableSecurityStore; import org.eclipse.leshan.server.security.SecurityChecker; import org.springframework.stereotype.Component; +import org.thingsboard.common.util.ThingsBoardThreadFactory; import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig; @@ -57,6 +59,8 @@ import java.security.spec.InvalidParameterSpecException; import java.security.spec.KeySpec; import java.security.spec.PKCS8EncodedKeySpec; import java.util.Arrays; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256; import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8; @@ -81,6 +85,7 @@ public class DefaultLwM2mTransportService implements LwM2MTransportService { private final CaliforniumRegistrationStore registrationStore; private final EditableSecurityStore securityStore; private final LwM2mClientContext lwM2mClientContext; + private ScheduledExecutorService registrationStoreExecutor; private LeshanServer server; @@ -112,6 +117,9 @@ public class DefaultLwM2mTransportService implements LwM2MTransportService { } private LeshanServer getLhServer() { +// this.registrationStoreExecutor = (ScheduledExecutorService) ThingsBoardExecutors.newWorkStealingPool(this.config.getRegistrationStorePoolSize(), "LwM2M registrationStore"); + this.registrationStoreExecutor = Executors.newScheduledThreadPool(this.config.getRegistrationStorePoolSize(), ThingsBoardThreadFactory.forName("LwM2M registrationStore")); + LeshanServerBuilder builder = new LeshanServerBuilder(); builder.setLocalAddress(config.getHost(), config.getPort()); builder.setLocalSecureAddress(config.getSecureHost(), config.getSecurePort()); @@ -119,6 +127,9 @@ public class DefaultLwM2mTransportService implements LwM2MTransportService { /* Use a magic converter to support bad type send by the UI. */ builder.setEncoder(new DefaultLwM2mNodeEncoder(LwM2mValueConverterImpl.getInstance())); + /* InMemoryRegistrationStore(ScheduledExecutorService schedExecutor, long cleanPeriodInSec) */ + InMemoryRegistrationStore registrationStore = new InMemoryRegistrationStore(this.registrationStoreExecutor, this.config.getCleanPeriodInSec()); + builder.setRegistrationStore(registrationStore); /* Create CoAP Config */ builder.setCoapConfig(getCoapConfig(config.getPort(), config.getSecurePort())); diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mServerListener.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mServerListener.java index f46b1c05f7..a93e969a3d 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mServerListener.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mServerListener.java @@ -88,7 +88,7 @@ public class LwM2mServerListener { public void cancelled(Observation observation) { String msg = String.format("%s: Cancel Observation %s.", LOG_LW2M_INFO, observation.getPath()); service.sendLogsToThingsboard(msg, observation.getRegistrationId()); - log.trace(msg); + log.warn(msg); } @Override diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportRequest.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportRequest.java index 0a5a545065..34dffaa29d 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportRequest.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportRequest.java @@ -19,6 +19,7 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.eclipse.californium.core.coap.CoAP; import org.eclipse.californium.core.coap.Response; +import org.eclipse.leshan.core.Link; import org.eclipse.leshan.core.model.ResourceModel; import org.eclipse.leshan.core.node.LwM2mNode; import org.eclipse.leshan.core.node.LwM2mPath; @@ -48,6 +49,7 @@ import org.eclipse.leshan.core.util.Hex; import org.eclipse.leshan.core.util.NamedThreadFactory; import org.eclipse.leshan.server.registration.Registration; import org.springframework.stereotype.Service; +import org.thingsboard.server.common.data.firmware.FirmwareUpdateStatus; import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig; import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient; @@ -69,14 +71,16 @@ import static org.eclipse.californium.core.coap.CoAP.ResponseCode.CONTENT; import static org.eclipse.leshan.core.ResponseCode.BAD_REQUEST; import static org.eclipse.leshan.core.ResponseCode.NOT_FOUND; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.DEFAULT_TIMEOUT; -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FR_PATH_RESOURCE_VER_ID; +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_PACKAGE_ID; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_ERROR; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_INFO; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_VALUE; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper; +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.DISCOVER_All; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.OBSERVE_CANCEL; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.OBSERVE_READ_ALL; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.RESPONSE_CHANNEL; +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SW_PACKAGE_ID; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertPathFromIdVerToObjectId; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertPathFromObjectIdToIdVer; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.createWriteAttributeRequest; @@ -132,7 +136,13 @@ public class LwM2mTransportRequest { break; case OBSERVE: if (resultIds.isResource()) { - request = new ObserveRequest(contentFormat, resultIds.getObjectId(), resultIds.getObjectInstanceId(), resultIds.getResourceId()); + Set observations = context.getServer().getObservationService().getObservations(registration); + Set paths = observations.stream().filter(observation -> observation.getPath().equals(resultIds)).collect(Collectors.toSet()); + if (paths.size() == 0) { + request = new ObserveRequest(contentFormat, resultIds.getObjectId(), resultIds.getObjectInstanceId(), resultIds.getResourceId()); + } else { + request = new ReadRequest(contentFormat, target); + } } else if (resultIds.isObjectInstance()) { request = new ObserveRequest(contentFormat, resultIds.getObjectId(), resultIds.getObjectInstanceId()); } else if (resultIds.getObjectId() >= 0) { @@ -197,11 +207,10 @@ public class LwM2mTransportRequest { targetIdVer, params, this.config.getModelProvider(), this.converter); - if (resources.size()>0) { + if (resources.size() > 0) { request = new WriteRequest(WriteRequest.Mode.UPDATE, contentFormat, resultIds.getObjectId(), resultIds.getObjectInstanceId(), resources); - } - else { + } else { Lwm2mClientRpcRequest rpcRequestClone = (Lwm2mClientRpcRequest) rpcRequest.clone(); if (rpcRequestClone != null) { String errorMsg = String.format("Path %s params is not valid", targetIdVer); @@ -250,15 +259,21 @@ public class LwM2mTransportRequest { String errorMsg = String.format("Path %s not found in object version", targetIdVer); serviceImpl.sentRpcRequest(rpcRequest, NOT_FOUND.getName(), errorMsg, LOG_LW2M_ERROR); } - } else if (OBSERVE_READ_ALL.name().equals(typeOper.name())) { - Set observations = context.getServer().getObservationService().getObservations(registration); - Set observationPaths = observations.stream().map(observation -> observation.getPath().toString()).collect(Collectors.toUnmodifiableSet()); - String msg = String.format("%s: type operation %s observation paths - %s", LOG_LW2M_INFO, - OBSERVE_READ_ALL.type, observationPaths); + } else if (OBSERVE_READ_ALL.name().equals(typeOper.name()) || DISCOVER_All.name().equals(typeOper.name())) { + Set paths; + if (OBSERVE_READ_ALL.name().equals(typeOper.name())) { + Set observations = context.getServer().getObservationService().getObservations(registration); + paths = observations.stream().map(observation -> observation.getPath().toString()).collect(Collectors.toUnmodifiableSet()); + } else { + Link[] objectLinks = registration.getSortedObjectLinks(); + paths = Arrays.stream(objectLinks).map(link -> link.toString()).collect(Collectors.toUnmodifiableSet()); + } + String msg = String.format("%s: type operation %s paths - %s", LOG_LW2M_INFO, + OBSERVE_READ_ALL.type, paths); serviceImpl.sendLogsToThingsboard(msg, registration.getId()); - log.trace("[{}] [{}], [{}]", typeOper.name(), registration.getEndpoint(), msg); + log.warn("[{}] [{}], [{}]", typeOper.name(), registration.getEndpoint(), msg); if (rpcRequest != null) { - String valueMsg = String.format("Observation paths - %s", observationPaths); + String valueMsg = String.format("Paths - %s", paths); serviceImpl.sentRpcRequest(rpcRequest, CONTENT.name(), valueMsg, LOG_LW2M_VALUE); } } @@ -284,6 +299,7 @@ public class LwM2mTransportRequest { private void sendRequest(Registration registration, LwM2mClient lwM2MClient, DownlinkRequest request, long timeoutInMs, Lwm2mClientRpcRequest rpcRequest) { context.getServer().send(registration, request, timeoutInMs, (ResponseCallback) response -> { + if (!lwM2MClient.isInit()) { lwM2MClient.initReadValue(this.serviceImpl, convertPathFromObjectIdToIdVer(request.getPath().toString(), registration)); } @@ -301,25 +317,21 @@ public class LwM2mTransportRequest { if (rpcRequest != null) { serviceImpl.sentRpcRequest(rpcRequest, response.getCode().getName(), response.getErrorMessage(), LOG_LW2M_ERROR); } - /* Not Found - set setClient_fw_version = empty - */ - if (FR_PATH_RESOURCE_VER_ID.equals(request.getPath().toString()) && lwM2MClient.isUpdateFw()) { - lwM2MClient.setUpdateFw(false); - lwM2MClient.getFrUpdate().setClientFwVersion(""); + /** Not Found + set setClient_fw_info... = empty + **/ + if (lwM2MClient.getFwUpdate().isInfoFwSwUpdate()) { + lwM2MClient.getFwUpdate().initReadValue(serviceImpl, request.getPath().toString()); log.warn("updateFirmwareClient1"); - serviceImpl.updateFirmwareClient(lwM2MClient); } } }, e -> { - /* version == null - set setClient_fw_version = empty - */ - if (FR_PATH_RESOURCE_VER_ID.equals(request.getPath().toString()) && lwM2MClient.isUpdateFw()) { - lwM2MClient.setUpdateFw(false); - lwM2MClient.getFrUpdate().setClientFwVersion(""); + /** version == null + set setClient_fw_info... = empty + **/ + if (lwM2MClient.getFwUpdate().isInfoFwSwUpdate()) { + lwM2MClient.getFwUpdate().initReadValue(serviceImpl, request.getPath().toString()); log.warn("updateFirmwareClient2"); - serviceImpl.updateFirmwareClient(lwM2MClient); } if (!lwM2MClient.isInit()) { lwM2MClient.initReadValue(this.serviceImpl, convertPathFromObjectIdToIdVer(request.getPath().toString(), registration)); @@ -458,21 +470,35 @@ public class LwM2mTransportRequest { Math.min(valueLength, config.getLogMaxLength()))); } value = valueLength > config.getLogMaxLength() ? value + "..." : value; - msg = String.format("%s: Update finished successfully: Lwm2m code - %d Resource path - %s length - %s value - %s", + msg = String.format("%s: Update finished successfully: Lwm2m code - %d Resource path: %s length: %s value: %s", LOG_LW2M_INFO, response.getCode().getCode(), request.getPath().toString(), valueLength, value); } else { value = this.converter.convertValue(singleResource.getValue(), singleResource.getType(), ResourceModel.Type.STRING, request.getPath()); - msg = String.format("%s: Update finished successfully: Lwm2m code - %d Resource path - %s value - %s", + msg = String.format("%s: Update finished successfully. Lwm2m code: %d Resource path: %s value: %s", LOG_LW2M_INFO, response.getCode().getCode(), request.getPath().toString(), value); } if (msg != null) { serviceImpl.sendLogsToThingsboard(msg, registration.getId()); - log.warn("[{}] [{}] [{}] - [{}] [{}] Update finished successfully: [{}]", request.getClass().getName(), registration.getEndpoint(), - ((Response) response.getCoapResponse()).getCode(), response.getCode(), request.getPath().toString(), value); + log.warn(msg); + if (request.getPath().toString().equals(FW_PACKAGE_ID) || request.getPath().toString().equals(SW_PACKAGE_ID)) { + this.executeFwSwUpdate(registration, request); + } } } catch (Exception e) { log.trace("Fail convert value from request to string. ", e); } } + + private void executeFwSwUpdate(Registration registration, DownlinkRequest request) { + LwM2mClient lwM2mClient = this.lwM2mClientContext.getClientByRegistrationId(registration.getId()); + if (request.getPath().toString().equals(FW_PACKAGE_ID) + && FirmwareUpdateStatus.DOWNLOADING.name().equals(lwM2mClient.getFwUpdate().getStateUpdate())) { + lwM2mClient.getFwUpdate().sendReadInfoForWrite(); + } + if (request.getPath().toString().equals(SW_PACKAGE_ID) + && FirmwareUpdateStatus.DOWNLOADING.name().equals(lwM2mClient.getSwUpdate().getStateUpdate())) { + lwM2mClient.getSwUpdate().sendReadInfoForWrite(); + } + } } diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportUtil.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportUtil.java index eddc5835c3..53881ac2c7 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportUtil.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportUtil.java @@ -43,6 +43,7 @@ import org.eclipse.leshan.server.registration.Registration; import org.nustaq.serialization.FSTConfiguration; import org.thingsboard.server.common.data.DeviceProfile; import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTransportConfiguration; +import org.thingsboard.server.common.data.firmware.FirmwareUpdateStatus; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.transport.TransportServiceCallback; import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient; @@ -70,6 +71,12 @@ import static org.eclipse.leshan.core.model.ResourceModel.Type.OBJLNK; import static org.eclipse.leshan.core.model.ResourceModel.Type.OPAQUE; import static org.eclipse.leshan.core.model.ResourceModel.Type.STRING; import static org.eclipse.leshan.core.model.ResourceModel.Type.TIME; +import static org.thingsboard.server.common.data.firmware.FirmwareUpdateStatus.DOWNLOADED; +import static org.thingsboard.server.common.data.firmware.FirmwareUpdateStatus.DOWNLOADING; +import static org.thingsboard.server.common.data.firmware.FirmwareUpdateStatus.FAILED; +import static org.thingsboard.server.common.data.firmware.FirmwareUpdateStatus.UPDATED; +import static org.thingsboard.server.common.data.firmware.FirmwareUpdateStatus.UPDATING; +import static org.thingsboard.server.common.data.firmware.FirmwareUpdateStatus.VERIFIED; import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_KEY; import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_PATH; @@ -107,11 +114,41 @@ public class LwM2mTransportUtil { public static final int LWM2M_STRATEGY_2 = 2; public static final String CLIENT_NOT_AUTHORIZED = "Client not authorized"; + public static final String LWM2M_VERSION_DEFAULT = "1.0"; - public static final Integer FR_OBJECT_ID = 5; - public static final Integer FR_RESOURCE_VER_ID = 7; - public static final String FR_PATH_RESOURCE_VER_ID = LWM2M_SEPARATOR_PATH + FR_OBJECT_ID + LWM2M_SEPARATOR_PATH - + "0" + LWM2M_SEPARATOR_PATH + FR_RESOURCE_VER_ID; + // FirmWare + public static final String FW_UPDATE = "Firmware update"; + public static final Integer FW_ID = 5; + // Package W + public static final String FW_PACKAGE_ID = "/5/0/0"; + // State R + public static final String FW_STATE_ID = "/5/0/3"; + // Update Result R + public static final String FW_RESULT_ID = "/5/0/5"; + // PkgName R + public static final String FW_NAME_ID = "/5/0/6"; + // PkgVersion R + public static final String FW_VER_ID = "/5/0/7"; + // Update E + public static final String FW_UPDATE_ID = "/5/0/2"; + + // SoftWare + public static final String SW_UPDATE = "Software update"; + public static final Integer SW_ID = 9; + // Package W + public static final String SW_PACKAGE_ID = "/9/0/2"; + // Update State R + public static final String SW_UPDATE_STATE_ID = "/9/0/7"; + // Update Result R + public static final String SW_RESULT_ID = "/9/0/9"; + // PkgName R + public static final String SW_NAME_ID = "/9/0/0"; + // PkgVersion R + public static final String SW_VER_ID = "/9/0/1"; + // Install E + public static final String SW_INSTALL_ID = "/9/0/4"; + // Uninstall E + public static final String SW_UN_INSTALL_ID = "/9/0/6"; public enum LwM2mTypeServer { BOOTSTRAP(0, "bootstrap"), @@ -144,19 +181,20 @@ public class LwM2mTransportUtil { */ READ(0, "Read"), DISCOVER(1, "Discover"), - OBSERVE_READ_ALL(2, "ObserveReadAll"), + DISCOVER_All(2, "DiscoverAll"), + OBSERVE_READ_ALL(3, "ObserveReadAll"), /** * POST */ - OBSERVE(3, "Observe"), - OBSERVE_CANCEL(4, "ObserveCancel"), - EXECUTE(5, "Execute"), + OBSERVE(4, "Observe"), + OBSERVE_CANCEL(5, "ObserveCancel"), + EXECUTE(6, "Execute"), /** * Replaces the Object Instance or the Resource(s) with the new value provided in the “Write” operation. (see * section 5.3.3 of the LW M2M spec). * if all resources are to be replaced */ - WRITE_REPLACE(6, "WriteReplace"), + WRITE_REPLACE(7, "WriteReplace"), /* PUT */ @@ -165,11 +203,13 @@ public class LwM2mTransportUtil { * 5.3.3 of the LW M2M spec). * if this is a partial update request */ - WRITE_UPDATE(7, "WriteUpdate"), - WRITE_ATTRIBUTES(8, "WriteAttributes"), - DELETE(9, "Delete"); + WRITE_UPDATE(8, "WriteUpdate"), + WRITE_ATTRIBUTES(9, "WriteAttributes"), + DELETE(10, "Delete"), -// READ_INFO_FW(10, "ReadInfoFirmware"); + // only for RPC + READ_INFO_FW(11, "ReadInfoFirmware"), + READ_INFO_SW(12, "ReadInfoSoftware"); public int code; public String type; @@ -189,10 +229,288 @@ public class LwM2mTransportUtil { } } + /** + * /** State R + * 0: Idle (before downloading or after successful updating) + * 1: Downloading (The data sequence is on the way) + * 2: Downloaded + * 3: Updating + */ + public enum StateFw { + IDLE(0, "Idle"), + DOWNLOADING(1, "Downloading"), + DOWNLOADED(2, "Downloaded"), + UPDATING(3, "Updating"); + + public int code; + public String type; + + StateFw(int code, String type) { + this.code = code; + this.type = type; + } + + public static StateFw fromStateFwByType(String type) { + for (StateFw to : StateFw.values()) { + if (to.type.equals(type)) { + return to; + } + } + throw new IllegalArgumentException(String.format("Unsupported FW State type : %s", type)); + } + + public static StateFw fromStateFwByCode(int code) { + for (StateFw to : StateFw.values()) { + if (to.code == code) { + return to; + } + } + throw new IllegalArgumentException(String.format("Unsupported FW State code : %s", code)); + } + } + + /** + * FW Update Result + * 0: Initial value. Once the updating process is initiated (Download /Update), this Resource MUST be reset to Initial value. + * 1: Firmware updated successfully. + * 2: Not enough flash memory for the new firmware package. + * 3: Out of RAM during downloading process. + * 4: Connection lost during downloading process. + * 5: Integrity check failure for new downloaded package. + * 6: Unsupported package type. + * 7: Invalid URI. + * 8: Firmware update failed. + * 9: Unsupported protocol. + */ + public enum UpdateResultFw { + INITIAL(0, "Initial value", false), + UPDATE_SUCCESSFULLY(1, "Firmware updated successfully", false), + NOT_ENOUGH(2, "Not enough flash memory for the new firmware package", false), + OUT_OFF_MEMORY(3, "Out of RAM during downloading process", false), + CONNECTION_LOST(4, "Connection lost during downloading process", true), + INTEGRITY_CHECK_FAILURE(5, "Integrity check failure for new downloaded package", true), + UNSUPPORTED_TYPE(6, "Unsupported package type", false), + INVALID_URI(7, "Invalid URI", false), + UPDATE_FAILED(8, "Firmware update failed", false), + UNSUPPORTED_PROTOCOL(9, "Unsupported protocol", false); + + public int code; + public String type; + public boolean isAgain; + + UpdateResultFw(int code, String type, boolean isAgain) { + this.code = code; + this.type = type; + this.isAgain = isAgain; + } + + public static UpdateResultFw fromUpdateResultFwByType(String type) { + for (UpdateResultFw to : UpdateResultFw.values()) { + if (to.type.equals(type)) { + return to; + } + } + throw new IllegalArgumentException(String.format("Unsupported FW Update Result type : %s", type)); + } + + public static UpdateResultFw fromUpdateResultFwByCode(int code) { + for (UpdateResultFw to : UpdateResultFw.values()) { + if (to.code == code) { + return to; + } + } + throw new IllegalArgumentException(String.format("Unsupported FW Update Result code : %s", code)); + } + } + + /** + * FirmwareUpdateStatus { + * DOWNLOADING, DOWNLOADED, VERIFIED, UPDATING, UPDATED, FAILED + */ + public static FirmwareUpdateStatus EqualsFwSateToFirmwareUpdateStatus(StateFw stateFw, UpdateResultFw updateResultFw) { + switch (updateResultFw) { + case INITIAL: + switch (stateFw) { + case IDLE: + return VERIFIED; + case DOWNLOADING: + return DOWNLOADING; + case DOWNLOADED: + return DOWNLOADED; + case UPDATING: + return UPDATING; + } + case UPDATE_SUCCESSFULLY: + return UPDATED; + case NOT_ENOUGH: + case OUT_OFF_MEMORY: + case CONNECTION_LOST: + case INTEGRITY_CHECK_FAILURE: + case UNSUPPORTED_TYPE: + case INVALID_URI: + case UPDATE_FAILED: + case UNSUPPORTED_PROTOCOL: + return FAILED; + default: + throw new CodecException("Invalid value stateFw %s %s for FirmwareUpdateStatus.", stateFw.name(), updateResultFw.name()); + } + } + + /** + * Update State R + * 0: INITIAL Before downloading. (see 5.1.2.1) + * 1: DOWNLOAD STARTED The downloading process has started and is on-going. (see 5.1.2.2) + * 2: DOWNLOADED The package has been completely downloaded (see 5.1.2.3) + * 3: DELIVERED In that state, the package has been correctly downloaded and is ready to be installed. (see 5.1.2.4) + * If executing the Install Resource failed, the state remains at DELIVERED. + * If executing the Install Resource was successful, the state changes from DELIVERED to INSTALLED. + * After executing the UnInstall Resource, the state changes to INITIAL. + * 4: INSTALLED + */ + public enum UpdateStateSw { + INITIAL(0, "Initial"), + DOWNLOAD_STARTED(1, "DownloadStarted"), + DOWNLOADED(2, "Downloaded"), + DELIVERED(3, "Delivered"), + INSTALLED(4, "Installed"); + + public int code; + public String type; + + UpdateStateSw(int code, String type) { + this.code = code; + this.type = type; + } + + public static UpdateStateSw fromUpdateStateSwByType(String type) { + for (UpdateStateSw to : UpdateStateSw.values()) { + if (to.type.equals(type)) { + return to; + } + } + throw new IllegalArgumentException(String.format("Unsupported SW State type : %s", type)); + } + + public static UpdateStateSw fromUpdateStateSwByCode(int code) { + for (UpdateStateSw to : UpdateStateSw.values()) { + if (to.code == code) { + return to; + } + } + throw new IllegalArgumentException(String.format("Unsupported SW State type : %s", code)); + } + } + + /** + * SW Update Result + * Contains the result of downloading or installing/uninstalling the software + * 0: Initial value. + * - Prior to download any new package in the Device, Update Result MUST be reset to this initial value. + * - One side effect of executing the Uninstall resource is to reset Update Result to this initial value "0". + * 1: Downloading. + * - The package downloading process is on-going. + * 2: Software successfully installed. + * 3: Successfully Downloaded and package integrity verified + * (( 4-49, for expansion, of other scenarios)) + * ** Failed + * 50: Not enough storage for the new software package. + * 51: Out of memory during downloading process. + * 52: Connection lost during downloading process. + * 53: Package integrity check failure. + * 54: Unsupported package type. + * 56: Invalid URI + * 57: Device defined update error + * 58: Software installation failure + * 59: Uninstallation Failure during forUpdate(arg=0) + * 60-200 : (for expansion, selection to be in blocks depending on new introduction of features) + * This Resource MAY be reported by sending Observe operation. + */ + public enum UpdateResultSw { + INITIAL(0, "Initial value", false), + DOWNLOADING(1, "Downloading", false), + SUCCESSFULLY_INSTALLED(2, "Software successfully installed", false), + SUCCESSFULLY_INSTALLED_VERIFIED(3, "Successfully Downloaded and package integrity verified", false), + NOT_ENOUGH_STORAGE(50, "Not enough storage for the new software package", true), + OUT_OFF_MEMORY(51, "Out of memory during downloading process", true), + CONNECTION_LOST(52, "Connection lost during downloading process", false), + PACKAGE_CHECK_FAILURE(53, "Package integrity check failure.", false), + UNSUPPORTED_PACKAGE_TYPE(54, "Unsupported package type", false), + INVALID_URI(56, "Invalid URI", true), + UPDATE_ERROR(57, "Device defined update error", true), + INSTALL_FAILURE(58, "Software installation failure", true), + UN_INSTALL_FAILURE(59, "Uninstallation Failure during forUpdate(arg=0)", true); + + public int code; + public String type; + public boolean isAgain; + + UpdateResultSw(int code, String type, boolean isAgain) { + this.code = code; + this.type = type; + this.isAgain = isAgain; + } + + public static UpdateResultSw fromUpdateResultSwByType(String type) { + for (UpdateResultSw to : UpdateResultSw.values()) { + if (to.type.equals(type)) { + return to; + } + } + throw new IllegalArgumentException(String.format("Unsupported SW Update Result type : %s", type)); + } + + public static UpdateResultSw fromUpdateResultSwByCode(int code) { + for (UpdateResultSw to : UpdateResultSw.values()) { + if (to.code == code) { + return to; + } + } + throw new IllegalArgumentException(String.format("Unsupported SW Update Result code : %s", code)); + } + } + + /** + * FirmwareUpdateStatus { + * DOWNLOADING, DOWNLOADED, VERIFIED, UPDATING, UPDATED, FAILED + */ + public static FirmwareUpdateStatus EqualsSwSateToFirmwareUpdateStatus(UpdateStateSw updateStateSw, UpdateResultSw updateResultSw) { + switch (updateResultSw) { + case INITIAL: + switch (updateStateSw) { + case INITIAL: + case DOWNLOAD_STARTED: + return DOWNLOADING; + case DOWNLOADED: + return DOWNLOADED; + case DELIVERED: + return VERIFIED; + } + case DOWNLOADING: + return DOWNLOADING; + case SUCCESSFULLY_INSTALLED: + return UPDATED; + case SUCCESSFULLY_INSTALLED_VERIFIED: + return VERIFIED; + case NOT_ENOUGH_STORAGE: + case OUT_OFF_MEMORY: + case CONNECTION_LOST: + case PACKAGE_CHECK_FAILURE: + case UNSUPPORTED_PACKAGE_TYPE: + case INVALID_URI: + case UPDATE_ERROR: + case INSTALL_FAILURE: + case UN_INSTALL_FAILURE: + return FAILED; + default: + throw new CodecException("Invalid value stateFw %s %s for FirmwareUpdateStatus.", updateStateSw.name(), updateResultSw.name()); + } + } + public static final String EVENT_AWAKE = "AWAKE"; public static final String RESPONSE_CHANNEL = "RESP"; - public static boolean equalsResourceValue(Object valueOld, Object valueNew, ResourceModel.Type type, LwM2mPath resourcePath) throws CodecException { + public static boolean equalsResourceValue(Object valueOld, Object valueNew, ResourceModel.Type type, LwM2mPath + resourcePath) throws CodecException { switch (type) { case BOOLEAN: case INTEGER: @@ -256,7 +574,7 @@ public class LwM2mTransportUtil { * "/3_1.0/0/9": {"pmax": 45}, "/3_1.2": {ver": "3_1.2"}} */ public static LwM2mClientProfile toLwM2MClientProfile(DeviceProfile deviceProfile) { - if (deviceProfile != null && ((Lwm2mDeviceProfileTransportConfiguration) deviceProfile.getProfileData().getTransportConfiguration()).getProperties().size() > 0) { + if (((Lwm2mDeviceProfileTransportConfiguration) deviceProfile.getProfileData().getTransportConfiguration()).getProperties().size() > 0) { Object profile = ((Lwm2mDeviceProfileTransportConfiguration) deviceProfile.getProfileData().getTransportConfiguration()).getProperties(); try { ObjectMapper mapper = new ObjectMapper(); @@ -375,7 +693,8 @@ public class LwM2mTransportUtil { return StringUtils.join(linkedListOut, ""); } - public static TransportServiceCallback getAckCallback(LwM2mClient lwM2MClient, int requestId, String typeTopic) { + public static TransportServiceCallback getAckCallback(LwM2mClient lwM2MClient, + int requestId, String typeTopic) { return new TransportServiceCallback() { @Override public void onSuccess(Void dummy) { @@ -420,7 +739,8 @@ public class LwM2mTransportUtil { return null; } - public static String validPathIdVer(String pathIdVer, Registration registration) throws IllegalArgumentException { + public static String validPathIdVer(String pathIdVer, Registration registration) throws + IllegalArgumentException { if (!pathIdVer.contains(LWM2M_SEPARATOR_PATH)) { throw new IllegalArgumentException(String.format("Error:")); } else { @@ -436,6 +756,7 @@ public class LwM2mTransportUtil { public static String convertPathFromObjectIdToIdVer(String path, Registration registration) { String ver = registration.getSupportedObject().get(new LwM2mPath(path).getObjectId()); + ver = ver != null ? ver : LWM2M_VERSION_DEFAULT; try { String[] keyArray = path.split(LWM2M_SEPARATOR_PATH); if (keyArray.length > 1) { @@ -531,7 +852,7 @@ public class LwM2mTransportUtil { case "ObjectLink": return OBJLNK; default: - return null; + return null; } } } diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClient.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClient.java index 691dd1d390..4e91bb1d50 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClient.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClient.java @@ -27,6 +27,7 @@ import org.eclipse.leshan.server.registration.Registration; import org.eclipse.leshan.server.security.SecurityInfo; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.DeviceProfile; +import org.thingsboard.server.common.data.firmware.FirmwareType; import org.thingsboard.server.gen.transport.TransportProtos.SessionInfoProto; import org.thingsboard.server.gen.transport.TransportProtos.TsKvProto; import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceCredentialsResponseMsg; @@ -49,8 +50,9 @@ import java.util.stream.Collectors; import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_PATH; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.TRANSPORT_DEFAULT_LWM2M_VERSION; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertPathFromIdVerToObjectId; -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.getVerFromPathIdVerOrId; +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertPathFromObjectIdToIdVer; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.equalsResourceTypeGetSimpleName; +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.getVerFromPathIdVerOrId; @Slf4j public class LwM2mClient implements Cloneable { @@ -74,25 +76,25 @@ public class LwM2mClient implements Cloneable { private UUID profileId; @Getter @Setter - private volatile LwM2mFirmwareUpdate frUpdate; + private volatile LwM2mFwSwUpdate fwUpdate; + @Getter + @Setter + private volatile LwM2mFwSwUpdate swUpdate; @Getter @Setter private Registration registration; - private ValidateDeviceCredentialsResponseMsg credentialsResponse; @Getter private final Map resources; @Getter private final Map delayedRequests; @Getter + @Setter private final List pendingReadRequests; @Getter private final Queue queuedRequests; @Getter private boolean init; - @Getter - @Setter - private volatile boolean updateFw; public Object clone() throws CloneNotSupportedException { return super.clone(); @@ -109,9 +111,9 @@ public class LwM2mClient implements Cloneable { this.profileId = profileId; this.sessionId = sessionId; this.init = false; - this.updateFw = false; this.queuedRequests = new ConcurrentLinkedQueue<>(); - this.frUpdate = new LwM2mFirmwareUpdate(); + this.fwUpdate = new LwM2mFwSwUpdate(this, FirmwareType.FIRMWARE); + this.swUpdate = new LwM2mFwSwUpdate(this, FirmwareType.SOFTWARE); if (this.credentialsResponse != null && this.credentialsResponse.hasDeviceInfo()) { this.session = createSession(nodeId, sessionId, credentialsResponse); this.deviceId = new UUID(session.getDeviceIdMSB(), session.getDeviceIdLSB()); @@ -164,15 +166,15 @@ public class LwM2mClient implements Cloneable { .build(); } - public boolean saveResourceValue(String pathRez, LwM2mResource rez, LwM2mModelProvider modelProvider) { - if (this.resources.get(pathRez) != null && this.resources.get(pathRez).getResourceModel() != null) { - this.resources.get(pathRez).setLwM2mResource(rez); + public boolean saveResourceValue(String pathRezIdVer, LwM2mResource rez, LwM2mModelProvider modelProvider) { + if (this.resources.get(pathRezIdVer) != null && this.resources.get(pathRezIdVer).getResourceModel() != null) { + this.resources.get(pathRezIdVer).setLwM2mResource(rez); return true; } else { - LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(pathRez)); + LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(pathRezIdVer)); ResourceModel resourceModel = modelProvider.getObjectModel(registration).getResourceModel(pathIds.getObjectId(), pathIds.getResourceId()); if (resourceModel != null) { - this.resources.put(pathRez, new ResourceValue(rez, resourceModel)); + this.resources.put(pathRezIdVer, new ResourceValue(rez, resourceModel)); return true; } else { return false; @@ -180,6 +182,16 @@ public class LwM2mClient implements Cloneable { } } + public Object getResourceValue (String pathRezIdVer, String pathRezId) { + String pathRez = pathRezIdVer == null ? convertPathFromObjectIdToIdVer(pathRezId, this.registration) : pathRezIdVer; + if (this.resources.get(pathRez) != null) { + return this.resources.get(pathRez).getLwM2mResource().isMultiInstances() ? + this.resources.get(pathRez).getLwM2mResource().getValues() : + this.resources.get(pathRez).getLwM2mResource().getValue(); + } + return null; + } + public ResourceModel getResourceModel(String pathIdVer, LwM2mModelProvider modelProvider) { LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(pathIdVer)); String verSupportedObject = registration.getSupportedObject().get(pathIds.getObjectId()); diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientContext.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientContext.java index 8e7f6a70ec..48c7b4db36 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientContext.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientContext.java @@ -54,7 +54,7 @@ public interface LwM2mClientContext { Map setProfiles(Map profiles); - LwM2mClientProfile toClientProfile(DeviceProfile deviceProfile); + LwM2mClientProfile profileUpdate(DeviceProfile deviceProfile); Set getSupportedIdVerInClient(Registration registration); diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientContextImpl.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientContextImpl.java index 3a7b652ab3..7986019d22 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientContextImpl.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientContextImpl.java @@ -16,6 +16,7 @@ package org.thingsboard.server.transport.lwm2m.server.client; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.eclipse.leshan.core.node.LwM2mPath; import org.eclipse.leshan.server.registration.Registration; import org.eclipse.leshan.server.security.EditableSecurityStore; @@ -40,6 +41,7 @@ import java.util.concurrent.ConcurrentHashMap; import static org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode.NO_SEC; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertPathFromObjectIdToIdVer; +@Slf4j @Service @TbLwM2mTransportComponent @RequiredArgsConstructor @@ -112,8 +114,12 @@ public class LwM2mClientContextImpl implements LwM2mClientContext { EndpointSecurityInfo securityInfo = lwM2MCredentialsSecurityInfoValidator.getEndpointSecurityInfo(endpoint, LwM2mTransportUtil.LwM2mTypeServer.CLIENT); if (securityInfo.getSecurityMode() < LwM2MSecurityMode.DEFAULT_MODE.code) { if (securityInfo.getDeviceProfile() != null) { - toClientProfile(securityInfo.getDeviceProfile()); - UUID profileUuid = securityInfo.getDeviceProfile().getUuidId(); + UUID profileUuid = profileUpdate(securityInfo.getDeviceProfile())!= null ? + securityInfo.getDeviceProfile().getUuidId() : null; + // TODO: for tests bug. + if (profileUuid== null) { + log.warn("input parameters toClientProfile if the result is null: [{}]", securityInfo.getDeviceProfile()); + } LwM2mClient client; if (securityInfo.getSecurityInfo() != null) { client = new LwM2mClient(context.getNodeId(), securityInfo.getSecurityInfo().getEndpoint(), @@ -162,13 +168,16 @@ public class LwM2mClientContextImpl implements LwM2mClientContext { } @Override - public LwM2mClientProfile toClientProfile(DeviceProfile deviceProfile) { - LwM2mClientProfile lwM2MClientProfile = profiles.get(deviceProfile.getUuidId()); - if (lwM2MClientProfile == null) { - lwM2MClientProfile = LwM2mTransportUtil.toLwM2MClientProfile(deviceProfile); + public LwM2mClientProfile profileUpdate(DeviceProfile deviceProfile) { + LwM2mClientProfile lwM2MClientProfile = deviceProfile != null ? + LwM2mTransportUtil.toLwM2MClientProfile(deviceProfile) : null; + if (lwM2MClientProfile != null) { profiles.put(deviceProfile.getUuidId(), lwM2MClientProfile); + return lwM2MClientProfile; + } + else { + return null; } - return lwM2MClientProfile; } /** diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mFirmwareUpdate.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mFirmwareUpdate.java deleted file mode 100644 index 9eb6321445..0000000000 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mFirmwareUpdate.java +++ /dev/null @@ -1,27 +0,0 @@ -/** - * Copyright © 2016-2021 The Thingsboard Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.thingsboard.server.transport.lwm2m.server.client; - -import lombok.Data; - -import java.util.UUID; - -@Data -public class LwM2mFirmwareUpdate { - private volatile String clientFwVersion; - private volatile String currentFwVersion; - private volatile UUID currentFwId; -} diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mFwSwUpdate.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mFwSwUpdate.java new file mode 100644 index 0000000000..38c918ed4d --- /dev/null +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mFwSwUpdate.java @@ -0,0 +1,333 @@ +/** + * Copyright © 2016-2021 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.transport.lwm2m.server.client; + +import lombok.Getter; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.eclipse.leshan.core.request.ContentFormat; +import org.thingsboard.server.common.data.firmware.FirmwareType; +import org.thingsboard.server.common.data.firmware.FirmwareUpdateStatus; +import org.thingsboard.server.gen.transport.TransportProtos; +import org.thingsboard.server.transport.lwm2m.server.DefaultLwM2MTransportMsgHandler; +import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import java.util.concurrent.CopyOnWriteArrayList; + +import static org.thingsboard.server.common.data.firmware.FirmwareKey.STATE; +import static org.thingsboard.server.common.data.firmware.FirmwareType.FIRMWARE; +import static org.thingsboard.server.common.data.firmware.FirmwareType.SOFTWARE; +import static org.thingsboard.server.common.data.firmware.FirmwareUtil.getAttributeKey; +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_NAME_ID; +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_PACKAGE_ID; +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_RESULT_ID; +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_STATE_ID; +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_UPDATE; +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_UPDATE_ID; +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_VER_ID; +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_INFO; +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.EXECUTE; +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.OBSERVE; +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.READ; +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.WRITE_REPLACE; +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SW_INSTALL_ID; +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SW_NAME_ID; +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SW_PACKAGE_ID; +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SW_RESULT_ID; +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SW_UN_INSTALL_ID; +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SW_UPDATE; +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SW_UPDATE_STATE_ID; +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SW_VER_ID; +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertPathFromObjectIdToIdVer; + +@Slf4j +public class LwM2mFwSwUpdate { + // 5/0/6 PkgName + // 9/0/0 PkgName + @Getter + @Setter + private volatile String currentTitle; + // 5/0/7 PkgVersion + // 9/0/1 PkgVersion + @Getter + @Setter + private volatile String currentVersion; + @Getter + @Setter + private volatile UUID currentId; + @Getter + @Setter + private volatile String stateUpdate; + @Getter + private String pathPackageId; + @Getter + private String pathStateId; + @Getter + private String pathResultId; + @Getter + private String pathNameId; + @Getter + private String pathVerId; + @Getter + private String pathInstallId; + @Getter + private String pathUnInstallId; + @Getter + private String wUpdate; + @Getter + @Setter + private volatile boolean infoFwSwUpdate = false; + private final FirmwareType type; + private DefaultLwM2MTransportMsgHandler serviceImpl; + @Getter + LwM2mClient lwM2MClient; + @Getter + @Setter + private final List pendingInfoRequestsStart; + + public LwM2mFwSwUpdate(LwM2mClient lwM2MClient, FirmwareType type) { + this.lwM2MClient = lwM2MClient; + this.pendingInfoRequestsStart = new CopyOnWriteArrayList<>(); + this.type = type; + this.stateUpdate = null; + this.initPathId(); + } + + private void initPathId() { + if (this.type.equals(FIRMWARE)) { + this.pathPackageId = FW_PACKAGE_ID; + this.pathStateId = FW_STATE_ID; + this.pathResultId = FW_RESULT_ID; + this.pathNameId = FW_NAME_ID; + this.pathVerId = FW_VER_ID; + this.pathInstallId = FW_UPDATE_ID; + this.wUpdate = FW_UPDATE; + } else if (this.type.equals(SOFTWARE)) { + this.pathPackageId = SW_PACKAGE_ID; + this.pathStateId = SW_UPDATE_STATE_ID; + this.pathResultId = SW_RESULT_ID; + this.pathNameId = SW_NAME_ID; + this.pathVerId = SW_VER_ID; + this.pathInstallId = SW_INSTALL_ID; + this.pathUnInstallId = SW_UN_INSTALL_ID; + this.wUpdate = SW_UPDATE; + } + } + + public void initReadValue(DefaultLwM2MTransportMsgHandler serviceImpl, String pathIdVer) { + if (this.serviceImpl == null) this.serviceImpl = serviceImpl; + if (pathIdVer != null) { + this.pendingInfoRequestsStart.remove(pathIdVer); + } + if (this.pendingInfoRequestsStart.size() == 0) { + this.infoFwSwUpdate = false; + if (!FirmwareUpdateStatus.DOWNLOADING.name().equals(this.stateUpdate)) { + boolean conditionalStart = this.type.equals(FIRMWARE) ? this.conditionalFwUpdateStart() : + this.conditionalSwUpdateStart(); + if (conditionalStart) { + this.stateUpdate = FirmwareUpdateStatus.DOWNLOADING.name(); + this.observeStateUpdate(); + this.writeFwSwWare(); + this.sendLogs(WRITE_REPLACE.name()); + } + } else { + boolean conditionalExecute = this.type.equals(FIRMWARE) ? conditionalFwUpdateExecute() : + conditionalSwUpdateExecute(); + if (conditionalExecute) { + this.stateUpdate = FirmwareUpdateStatus.DOWNLOADED.name(); + this.observeStateUpdate(); + this.executeFwSwWare(); + this.sendLogs(EXECUTE.name()); + } + } + } + } + + private void writeFwSwWare() { + int chunkSize = 0; + int chunk = 0; + byte[] firmwareChunk = this.serviceImpl.firmwareDataCache.get(this.currentId.toString(), chunkSize, chunk); + String targetIdVer = convertPathFromObjectIdToIdVer(this.pathPackageId, this.lwM2MClient.getRegistration()); + this.serviceImpl.lwM2mTransportRequest.sendAllRequest(lwM2MClient.getRegistration(), targetIdVer, WRITE_REPLACE, ContentFormat.OPAQUE.getName(), + firmwareChunk, this.serviceImpl.config.getTimeout(), null); + } + + public void sendLogs(String typeOper) { + this.sendSateOnThingsboard(); + String msg = String.format("%s: %s, %s, pkgVer: %s: pkgName - %s.", + LOG_LW2M_INFO, this.wUpdate, typeOper, this.currentVersion, this.currentTitle); + serviceImpl.sendLogsToThingsboard(msg, lwM2MClient.getRegistration().getId()); + log.warn("{} state: [{}]", msg, this.stateUpdate); + } + + public void executeFwSwWare() { + this.serviceImpl.lwM2mTransportRequest.sendAllRequest(this.lwM2MClient.getRegistration(), this.pathInstallId, EXECUTE, ContentFormat.TLV.getName(), + null, 0, null); + } + + + /** + * FW: start + * Проверяем состояние State (5.3) и Update Result (5.5). + * 1. Если Update Result > 1 (some errors) - Это означает что пред. апдейт не прошел. + * - Запускаем апдейт в независимости от состяния прошивки и ее версии. + * 2. Если Update Result = 1 && State = 0 - Это означает что пред. апдейт прошел. + * 3. Если Update Result = 0 && State = 0 && Ver = "" - Это означает что апдейта еще не было. + * - Проверяем поменялась ли версия и запускаем новый апдейт. + * Новый апдейт: + * 1. Запись новой прошивки в Lwm2mClient + * 2. Мониторим итог зиписи: + * 2.1 State = 2 "Downloaded" и Update Result = 0 "INITIAL" стартуем Update 5.2 (Execute): + * Мониторим состояние Update Result и State и мапим его на наш enum (DOWNLOADING, DOWNLOADED, VERIFIED, UPDATING, UPDATED, FAILED) + * + пишем лог (в телеметрию отдельным полем error) с подробным статусом. + * + * @valerii.sosliuk Вопрос к клиенту - как будем реагировать на Failed update? Когда повторять операцию? + * - На update reg? + * - Или клиент должен послать комканду на рестарт девайса? + * - или переодически? + * отправили прошивку мониторим: + * -- Observe "Update Result" id=5 && "State" id=3 + * --- "Update Result" id=5 value must be = 0 + * --- "State" id=3 value must be > 0 + * --- to telemetry - DOWNLOADING + * "Update Result" id=5 value change > 1 "Firmware updated not successfully" отправили прошивку: telemetry - FAILED + * "Update Result" id=5 value change ==1 "State" id=3 value == 0 "Firmware updated successfully" отправили прошивку: telemetry - UPDATED + */ + private boolean conditionalFwUpdateStart() { + Long stateFw = (Long) this.lwM2MClient.getResourceValue(null, this.pathStateId); + Long updateResultFw = (Long) this.lwM2MClient.getResourceValue(null, this.pathResultId); + String pkgName = (String) this.lwM2MClient.getResourceValue(null, this.pathNameId); + // #1/#2 + return updateResultFw > LwM2mTransportUtil.UpdateResultFw.UPDATE_SUCCESSFULLY.code || + ( + ( + (stateFw == LwM2mTransportUtil.StateFw.IDLE.code && updateResultFw == LwM2mTransportUtil.UpdateResultFw.UPDATE_SUCCESSFULLY.code) || + (stateFw == LwM2mTransportUtil.StateFw.IDLE.code && updateResultFw == LwM2mTransportUtil.UpdateResultFw.INITIAL.code + && StringUtils.trimToEmpty(pkgName).isEmpty()) + ) && + ( + (this.currentVersion != null && !this.currentVersion.equals(this.lwM2MClient.getResourceValue(null, this.pathVerId))) || + (this.currentTitle != null && !this.currentTitle.equals(this.lwM2MClient.getResourceValue(null, this.pathNameId))) + ) + ); +// if (condFwUpdateStart) { +// this.sendSateOnThingsboard(stateFw, updateResultFw, pkgName); +// } +// return condFwUpdateStart; + } + + private boolean conditionalFwUpdateExecute() { + Long state = (Long) this.lwM2MClient.getResourceValue(null, this.pathStateId); + Long updateResult = (Long) this.lwM2MClient.getResourceValue(null, this.pathResultId); + // #1/#2 + return updateResult == LwM2mTransportUtil.UpdateResultFw.INITIAL.code && state == LwM2mTransportUtil.StateFw.DOWNLOADED.code; + } + + /** + * FW: start + * Проверяем состояние Update_State (9.7) и Update_Result (9.9). + * 1. Если Update Result > 3 (some errors) - Это означает что пред. апдейт не прошел. + * - Запускаем апдейт в независимости от состяния прошивки и ее версии. + * 2. Если Update Result = 2 && Update State = 4 - Это означает что пред. апдейт прошел + * 3. Если Update Result = 0 && Update State = 0 && Ver = "" - Это означает что апдейта еще не было. + * 4. Если Update Result = 0 && Update State = 0 - Это означает что пред. апдейт UnInstall + * - Проверяем поменялась ли версия и запускаем новый апдейт. + * Новый апдейт: + * 1. Запись новой прошивки в Lwm2mClient + * 2. Мониторим итог зиписи: + * 2.1 Update State = 3 "DELIVERED" стартуем Install 9.4 (Execute): + * Мониторим состояние Update Result и State и мапим его на наш enum (DOWNLOADING, DOWNLOADED, VERIFIED, UPDATING, UPDATED, FAILED) + * + пишем лог (в телеметрию отдельным полем error) с подробным статусом. + */ + private boolean conditionalSwUpdateStart() { + Long updateState = (Long) this.lwM2MClient.getResourceValue(null, this.pathStateId); + Long updateResult = (Long) this.lwM2MClient.getResourceValue(null, this.pathResultId); + String pkgName = (String) this.lwM2MClient.getResourceValue(null, this.pathNameId); + // #1/#2 + return updateResult > LwM2mTransportUtil.UpdateResultSw.SUCCESSFULLY_INSTALLED_VERIFIED.code || + ( + ( + ( + ( + (updateState == LwM2mTransportUtil.UpdateStateSw.INSTALLED.code && updateResult == LwM2mTransportUtil.UpdateResultSw.SUCCESSFULLY_INSTALLED.code) || + (updateState == LwM2mTransportUtil.UpdateStateSw.INITIAL.code && updateResult == LwM2mTransportUtil.UpdateResultSw.INITIAL.code && + StringUtils.trimToEmpty(pkgName).isEmpty()) + ) + ) && + (updateState == LwM2mTransportUtil.UpdateStateSw.INITIAL.code && updateResult == LwM2mTransportUtil.UpdateResultSw.INITIAL.code) + ) && + ( + (this.currentVersion != null && !this.currentVersion.equals(this.lwM2MClient.getResourceValue(null, this.pathVerId))) || + (this.currentTitle != null && !this.currentTitle.equals(this.lwM2MClient.getResourceValue(null, this.pathNameId))) + ) + ); +// return condSwUpdateStart; + } + + private boolean conditionalSwUpdateExecute() { + Long updateState = (Long) this.lwM2MClient.getResourceValue(null, this.pathStateId); + Long updateResult = (Long) this.lwM2MClient.getResourceValue(null, this.pathResultId); + // #1/#2 + return (updateResult == LwM2mTransportUtil.UpdateResultSw.INITIAL.code || updateResult == LwM2mTransportUtil.UpdateResultSw.SUCCESSFULLY_INSTALLED_VERIFIED.code) && + updateState == LwM2mTransportUtil.UpdateStateSw.DELIVERED.code; + } + + private void observeStateUpdate() { + this.serviceImpl.lwM2mTransportRequest.sendAllRequest(lwM2MClient.getRegistration(), + convertPathFromObjectIdToIdVer(this.pathStateId, this.lwM2MClient.getRegistration()), OBSERVE, + null, null, 0, null); + this.serviceImpl.lwM2mTransportRequest.sendAllRequest(lwM2MClient.getRegistration(), + convertPathFromObjectIdToIdVer(this.pathResultId, this.lwM2MClient.getRegistration()), OBSERVE, + null, null, 0, null); + } + + public void sendSateOnThingsboard() { + if (StringUtils.trimToNull(this.stateUpdate) != null) { + List result = new ArrayList<>(); + TransportProtos.KeyValueProto.Builder kvProto = TransportProtos.KeyValueProto.newBuilder().setKey(getAttributeKey(this.type, STATE)); + kvProto.setType(TransportProtos.KeyValueType.STRING_V).setStringV(stateUpdate); + result.add(kvProto.build()); + this.serviceImpl.helper.sendParametersOnThingsboardTelemetry(result, + this.serviceImpl.getSessionInfoOrCloseSession(this.lwM2MClient.getRegistration())); + } + } + + public void sendReadInfo(DefaultLwM2MTransportMsgHandler serviceImpl) { + this.serviceImpl = this.serviceImpl == null ? serviceImpl : this.serviceImpl; + this.pendingInfoRequestsStart.add(convertPathFromObjectIdToIdVer( + this.pathVerId, this.lwM2MClient.getRegistration())); + this.pendingInfoRequestsStart.add(convertPathFromObjectIdToIdVer( + this.pathNameId, this.lwM2MClient.getRegistration())); + this.sendReadInfoForWrite(); + } + + public void sendReadInfoForWrite() { + + this.infoFwSwUpdate = true; + this.pendingInfoRequestsStart.add(convertPathFromObjectIdToIdVer( + this.pathStateId, this.lwM2MClient.getRegistration())); + this.pendingInfoRequestsStart.add(convertPathFromObjectIdToIdVer( + this.pathResultId, this.lwM2MClient.getRegistration())); + this.pendingInfoRequestsStart.forEach(pathIdVer -> { + this.serviceImpl.lwM2mTransportRequest.sendAllRequest(this.lwM2MClient.getRegistration(), pathIdVer, READ, ContentFormat.TLV.getName(), + null, 0, null); + }); + } +} diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/Lwm2mClientRpcRequest.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/Lwm2mClientRpcRequest.java index 0f0bd34024..77a26b4755 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/Lwm2mClientRpcRequest.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/Lwm2mClientRpcRequest.java @@ -17,6 +17,7 @@ package org.thingsboard.server.transport.lwm2m.server.client; import com.google.gson.JsonObject; import lombok.Data; +import lombok.extern.slf4j.Slf4j; import org.eclipse.leshan.core.request.ContentFormat; import org.eclipse.leshan.server.registration.Registration; import org.thingsboard.server.gen.transport.TransportProtos; @@ -27,6 +28,7 @@ import java.util.concurrent.ConcurrentHashMap; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.validPathIdVer; +@Slf4j @Data public class Lwm2mClientRpcRequest { public final String targetIdVerKey = "targetIdVer"; @@ -113,7 +115,7 @@ public class Lwm2mClientRpcRequest { try { return super.clone(); } catch (CloneNotSupportedException e) { - e.printStackTrace(); + log.error("", e); } return null; }