diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/secure/LwM2MBootstrapSecurityStore.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/secure/LwM2MBootstrapSecurityStore.java index 0a55d2c3cb..036e4c10b7 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/secure/LwM2MBootstrapSecurityStore.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/secure/LwM2MBootstrapSecurityStore.java @@ -47,6 +47,7 @@ import java.util.UUID; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.BOOTSTRAP_SERVER; 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_TELEMETRY; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LWM2M_SERVER; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SERVERS; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.getBootstrapParametersFromThingsboard; @@ -167,13 +168,13 @@ public class LwM2MBootstrapSecurityStore implements BootstrapSecurityStore { lwM2MBootstrapConfig.bootstrapServer = new LwM2MServerBootstrap(lwM2MBootstrapConfig.bootstrapServer, profileServerBootstrap); lwM2MBootstrapConfig.lwm2mServer = new LwM2MServerBootstrap(lwM2MBootstrapConfig.lwm2mServer, profileLwm2mServer); String logMsg = String.format("%s: getParametersBootstrap: %s Access connect client with bootstrap server.", LOG_LW2M_INFO, store.getEndPoint()); - helper.sendParametersOnThingsboardTelemetry(helper.getKvLogyToThingsboard(logMsg), sessionInfo); + helper.sendParametersOnThingsboardTelemetry(helper.getKvStringtoThingsboard(LOG_LW2M_TELEMETRY, logMsg), sessionInfo); return lwM2MBootstrapConfig; } else { log.error(" [{}] Different values SecurityMode between of client and profile.", store.getEndPoint()); log.error("{} getParametersBootstrap: [{}] Different values SecurityMode between of client and profile.", LOG_LW2M_ERROR, store.getEndPoint()); String logMsg = String.format("%s: getParametersBootstrap: %s Different values SecurityMode between of client and profile.", LOG_LW2M_ERROR, store.getEndPoint()); - helper.sendParametersOnThingsboardTelemetry(helper.getKvLogyToThingsboard(logMsg), sessionInfo); + helper.sendParametersOnThingsboardTelemetry(helper.getKvStringtoThingsboard(LOG_LW2M_TELEMETRY, logMsg), sessionInfo); return null; } } 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 683420e66b..593b56a499 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 @@ -156,9 +156,7 @@ public class LwM2MTransportServerConfig implements LwM2MSecureServerConfig { keyStoreValue = KeyStore.getInstance(keyStoreType); keyStoreValue.load(inKeyStore, keyStorePassword == null ? null : keyStorePassword.toCharArray()); } catch (Exception e) { - log.warn("Unable to lookup LwM2M keystore. Reason: {}, {}" , uri, e.getMessage()); -// Absence of the key store should not block user from using plain LwM2M -// throw new RuntimeException("Failed to lookup LwM2M keystore: " + (uri != null ? uri.toString() : ""), e); + log.trace("Unable to lookup LwM2M keystore. Reason: {}, {}" , uri, e.getMessage()); } } } 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 71cc2f11ee..bf4b4cefee 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 @@ -23,13 +23,12 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.reflect.TypeToken; import lombok.extern.slf4j.Slf4j; +import org.eclipse.leshan.core.model.ObjectModel; import org.eclipse.leshan.core.model.ResourceModel; -import org.eclipse.leshan.core.node.LwM2mMultipleResource; import org.eclipse.leshan.core.node.LwM2mObject; import org.eclipse.leshan.core.node.LwM2mObjectInstance; import org.eclipse.leshan.core.node.LwM2mPath; import org.eclipse.leshan.core.node.LwM2mResource; -import org.eclipse.leshan.core.node.LwM2mSingleResource; import org.eclipse.leshan.core.observation.Observation; import org.eclipse.leshan.core.request.ContentFormat; import org.eclipse.leshan.core.request.WriteRequest; @@ -44,7 +43,6 @@ 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; @@ -57,6 +55,7 @@ import org.thingsboard.server.gen.transport.TransportProtos.SessionEvent; import org.thingsboard.server.gen.transport.TransportProtos.SessionInfoProto; import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig; +import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper; import org.thingsboard.server.transport.lwm2m.server.adaptors.LwM2MJsonAdaptor; import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient; import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext; @@ -85,19 +84,19 @@ 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.firmware.FirmwareUpdateStatus.DOWNLOADED; +import static org.thingsboard.server.common.data.firmware.FirmwareUpdateStatus.UPDATING; 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.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_TELEMETRY; 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; @@ -109,6 +108,7 @@ import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.L import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.WRITE_REPLACE; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.WRITE_UPDATE; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SW_ID; +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SW_RESULT_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; @@ -123,7 +123,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler private ExecutorService registrationExecutor; private ExecutorService updateRegistrationExecutor; - private ExecutorService unregistrationExecutor; + private ExecutorService unRegistrationExecutor; private LwM2mValueConverterImpl converter; private final TransportService transportService; @@ -155,7 +155,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler this.context.getScheduler().scheduleAtFixedRate(this::reportActivity, new Random().nextInt((int) config.getSessionReportTimeout()), config.getSessionReportTimeout(), TimeUnit.MILLISECONDS); this.registrationExecutor = ThingsBoardExecutors.newWorkStealingPool(this.config.getRegisteredPoolSize(), "LwM2M registration"); this.updateRegistrationExecutor = ThingsBoardExecutors.newWorkStealingPool(this.config.getUpdateRegisteredPoolSize(), "LwM2M update registration"); - this.unregistrationExecutor = ThingsBoardExecutors.newWorkStealingPool(this.config.getUnRegisteredPoolSize(), "LwM2M unregistration"); + this.unRegistrationExecutor = ThingsBoardExecutors.newWorkStealingPool(this.config.getUnRegisteredPoolSize(), "LwM2M unRegistration"); this.converter = LwM2mValueConverterImpl.getInstance(); } @@ -219,11 +219,14 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler request.send(); } } + this.sendLogsToThingsboard(LOG_LW2M_INFO + ": Client update Registration", registration.getId()); } else { log.error("Client: [{}] updatedReg [{}] name [{}] sessionInfo ", registration.getId(), registration.getEndpoint(), null); + this.sendLogsToThingsboard(LOG_LW2M_ERROR + ": Client update Registration", registration.getId()); } } catch (Throwable t) { log.error("[{}] endpoint [{}] error Unable update registration.", registration.getEndpoint(), t); + this.sendLogsToThingsboard(LOG_LW2M_ERROR + String.format(": Client update Registration, %s", t.getMessage()), registration.getId()); } }); } @@ -234,13 +237,14 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler * !!! Warn: if have not finishing unReg, then this operation will be finished on next Client`s connect */ public void unReg(Registration registration, Collection observations) { - unregistrationExecutor.submit(() -> { + unRegistrationExecutor.submit(() -> { try { - this.setCancelObservations(registration); + this.setCancelObservationsAll(registration); this.sendLogsToThingsboard(LOG_LW2M_INFO + ": Client unRegistration", registration.getId()); - this.closeClientSession(registration); + this.closeClientSession(registration); ; } catch (Throwable t) { log.error("[{}] endpoint [{}] error Unable un registration.", registration.getEndpoint(), t); + this.sendLogsToThingsboard(LOG_LW2M_ERROR + String.format(": Client Unable un Registration, %s", t.getMessage()), registration.getId()); } }); } @@ -265,13 +269,18 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler //TODO: associate endpointId with device information. } + /** + * Cancel observation for All objects for this registration + */ @Override - public void setCancelObservations(Registration registration) { + public void setCancelObservationsAll(Registration registration) { if (registration != null) { - Set observations = context.getServer().getObservationService().getObservations(registration); - observations.forEach(observation -> lwM2mTransportRequest.sendAllRequest(registration, - convertPathFromObjectIdToIdVer(observation.getPath().toString(), registration), OBSERVE_CANCEL, - null, null, this.config.getTimeout(), null)); + lwM2mTransportRequest.sendAllRequest(registration, null, OBSERVE_CANCEL, + null, null, this.config.getTimeout(), null); +// Set observations = context.getServer().getObservationService().getObservations(registration); +// observations.forEach(observation -> lwM2mTransportRequest.sendAllRequest(registration, +// convertPathFromObjectIdToIdVer(observation.getPath().toString(), registration), OBSERVE_CANCEL, +// null, null, this.config.getTimeout(), null)); } } @@ -285,34 +294,43 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler @Override public void onUpdateValueAfterReadResponse(Registration registration, String path, ReadResponse response, Lwm2mClientRpcRequest rpcRequest) { if (response.getContent() != null) { - Object value = null; - if (response.getContent() instanceof LwM2mObject) { - LwM2mObject lwM2mObject = (LwM2mObject) response.getContent(); - if (rpcRequest != null) { - value = lwM2mObject.toString(); + LwM2mClient lwM2MClient = clientContext.getOrRegister(registration); + ObjectModel objectModelVersion = lwM2MClient.getObjectModel(path, this.config.getModelProvider()); + if (objectModelVersion != null) { + if (response.getContent() instanceof LwM2mObject) { + LwM2mObject lwM2mObject = (LwM2mObject) response.getContent(); + this.updateObjectResourceValue(registration, lwM2mObject, path); + } else if (response.getContent() instanceof LwM2mObjectInstance) { + LwM2mObjectInstance lwM2mObjectInstance = (LwM2mObjectInstance) response.getContent(); + this.updateObjectInstanceResourceValue(registration, lwM2mObjectInstance, path); + } else if (response.getContent() instanceof LwM2mResource) { + LwM2mResource lwM2mResource = (LwM2mResource) response.getContent(); + this.updateResourcesValue(registration, lwM2mResource, path); } - this.updateObjectResourceValue(registration, lwM2mObject, path); - } else if (response.getContent() instanceof LwM2mObjectInstance) { - LwM2mObjectInstance lwM2mObjectInstance = (LwM2mObjectInstance) response.getContent(); - if (rpcRequest != null) { - value = lwM2mObjectInstance.toString(); - } - this.updateObjectInstanceResourceValue(registration, lwM2mObjectInstance, path); - } else if (response.getContent() instanceof LwM2mResource) { - LwM2mResource lwM2mResource = (LwM2mResource) response.getContent(); - if (rpcRequest != null) { - value = lwM2mResource.isMultiInstances() ? ((LwM2mMultipleResource) lwM2mResource).toString() : - ((LwM2mSingleResource) lwM2mResource).toString(); - } - this.updateResourcesValue(registration, lwM2mResource, path); } if (rpcRequest != null) { - rpcRequest.setValueMsg(String.format("%s", value)); - this.sentRpcRequest(rpcRequest, response.getCode().getName(), (String) value, LOG_LW2M_VALUE); + this.sendRpcRequestAfterReadResponse(registration, lwM2MClient, path, response, rpcRequest); } } } + private void sendRpcRequestAfterReadResponse(Registration registration, LwM2mClient lwM2MClient, String pathIdVer, ReadResponse response, + Lwm2mClientRpcRequest rpcRequest) { + Object value = null; + if (response.getContent() instanceof LwM2mObject) { + value = lwM2MClient.objectToString((LwM2mObject) response.getContent(), this.converter, pathIdVer); + } else if (response.getContent() instanceof LwM2mObjectInstance) { + value = lwM2MClient.instanceToString((LwM2mObjectInstance) response.getContent(), this.converter, pathIdVer); + } else if (response.getContent() instanceof LwM2mResource) { + value = lwM2MClient.resourceToString ((LwM2mResource) response.getContent(), this.converter, pathIdVer); + } + String msg = String.format("%s: type operation %s path - %s value - %s", LOG_LW2M_INFO, + READ, pathIdVer, value); + this.sendLogsToThingsboard(msg, registration.getId()); + rpcRequest.setValueMsg(String.format("%s", value)); + this.sentRpcRequest(rpcRequest, response.getCode().getName(), (String) value, LOG_LW2M_VALUE); + } + /** * Update - send request in change value resources in Client * 1. FirmwareUpdate: @@ -411,12 +429,12 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler } @Override - public void onToDeviceRpcRequest(TransportProtos.ToDeviceRpcRequestMsg toDeviceRequest, SessionInfoProto sessionInfo) { + public void onToDeviceRpcRequest(TransportProtos.ToDeviceRpcRequestMsg toDeviceRpcRequestMsg, SessionInfoProto sessionInfo) { + log.warn("4) RPC-OK finish to [{}]", toDeviceRpcRequestMsg); Lwm2mClientRpcRequest lwm2mClientRpcRequest = null; try { - log.info("[{}] toDeviceRpcRequest", toDeviceRequest); Registration registration = clientContext.getClient(new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB())).getRegistration(); - lwm2mClientRpcRequest = this.getDeviceRpcRequest(toDeviceRequest, sessionInfo, registration); + lwm2mClientRpcRequest = this.getDeviceRpcRequest(toDeviceRpcRequestMsg, sessionInfo, registration); if (lwm2mClientRpcRequest.getErrorMsg() != null) { lwm2mClientRpcRequest.setResponseCode(BAD_REQUEST.name()); this.onToDeviceRpcResponse(lwm2mClientRpcRequest.getDeviceRpcResponseResultMsg(), sessionInfo); @@ -486,7 +504,8 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler } lwm2mClientRpcRequest.setSessionInfo(sessionInfo); if (!(OBSERVE_READ_ALL == lwm2mClientRpcRequest.getTypeOper() - || DISCOVER_All == lwm2mClientRpcRequest.getTypeOper()) + || DISCOVER_All == lwm2mClientRpcRequest.getTypeOper() + || OBSERVE_CANCEL == lwm2mClientRpcRequest.getTypeOper()) && lwm2mClientRpcRequest.getTargetIdVer() == null) { lwm2mClientRpcRequest.setErrorMsg(lwm2mClientRpcRequest.targetIdVerKey + " and " + lwm2mClientRpcRequest.keyNameKey + " is null or bad format"); @@ -599,7 +618,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler */ @Override public void onAwakeDev(Registration registration) { - log.info("[{}] [{}] Received endpoint Awake version event", registration.getId(), registration.getEndpoint()); + log.trace("[{}] [{}] Received endpoint Awake version event", registration.getId(), registration.getEndpoint()); this.sendLogsToThingsboard(LOG_LW2M_INFO + ": Client is awake!", registration.getId()); //TODO: associate endpointId with device information. } @@ -615,7 +634,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler if (logMsg.length() > 1024) { logMsg = logMsg.substring(0, 1024); } - this.helper.sendParametersOnThingsboardTelemetry(this.helper.getKvLogyToThingsboard(logMsg), sessionInfo); + this.helper.sendParametersOnThingsboardTelemetry(this.helper.getKvStringtoThingsboard(LOG_LW2M_TELEMETRY, logMsg), sessionInfo); } } @@ -699,22 +718,54 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler 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())) { + /** + * Before operation Execute (FwUpdate) inspection Update Result : + * - after finished operation Write result: success (FwUpdate): fw_state = DOWNLOADED + * - before start operation Execute (FwUpdate) Update Result = 0 - Initial value + * - start Execute (FwUpdate) + * After finished operation Execute (FwUpdate) inspection Update Result : + * - after start operation Execute (FwUpdate): fw_state = UPDATING + * - after success finished operation Execute (FwUpdate) Update Result == 1 ("Firmware updated successfully") + * - finished operation Execute (FwUpdate) + */ + if (lwM2MClient.getFwUpdate() != null + && (convertPathFromObjectIdToIdVer(FW_RESULT_ID, registration).equals(path))) { + if (DOWNLOADED.name().equals(lwM2MClient.getFwUpdate().getStateUpdate()) + && lwM2MClient.getFwUpdate().conditionalFwExecuteStart()) { + lwM2MClient.getFwUpdate().executeFwSwWare(); + } else if (UPDATING.name().equals(lwM2MClient.getFwUpdate().getStateUpdate()) + && lwM2MClient.getFwUpdate().conditionalFwExecuteAfterSuccess()) { + lwM2MClient.getFwUpdate().finishFwSwUpdate(true); + } else if (UPDATING.name().equals(lwM2MClient.getFwUpdate().getStateUpdate()) + && lwM2MClient.getFwUpdate().conditionalFwExecuteAfterError()) { + lwM2MClient.getFwUpdate().finishFwSwUpdate(false); + } + } + + /** + * Before operation Execute (SwUpdate) inspection Update Result : + * - after finished operation Write result: success (SwUpdate): fw_state = DOWNLOADED + * - before operation Execute (SwUpdate) Update Result = 3 - Successfully Downloaded and package integrity verified + * - start Execute (SwUpdate) + * After finished operation Execute (SwUpdate) inspection Update Result : + * - after start operation Execute (SwUpdate): fw_state = UPDATING + * - after success finished operation Execute (SwUpdate) Update Result == 2 "Software successfully installed."" + * - after success finished operation Execute (SwUpdate) Update Result == 2 "Software successfully installed."" + * - finished operation Execute (SwUpdate) + */ + if (lwM2MClient.getSwUpdate() != null + && (convertPathFromObjectIdToIdVer(SW_RESULT_ID, registration).equals(path))) { + if (DOWNLOADED.name().equals(lwM2MClient.getSwUpdate().getStateUpdate()) + && lwM2MClient.getSwUpdate().conditionalSwUpdateExecute()) { + lwM2MClient.getSwUpdate().executeFwSwWare(); + } else if (UPDATING.name().equals(lwM2MClient.getSwUpdate().getStateUpdate()) + && lwM2MClient.getSwUpdate().conditionalSwExecuteAfterSuccess()) { + lwM2MClient.getSwUpdate().finishFwSwUpdate(true); + } else if (UPDATING.name().equals(lwM2MClient.getSwUpdate().getStateUpdate()) + && lwM2MClient.getSwUpdate().conditionalSwExecuteAfterError()) { + lwM2MClient.getSwUpdate().finishFwSwUpdate(false); + } } Set paths = new HashSet<>(); paths.add(path); @@ -736,7 +787,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler */ private void updateAttrTelemetry(Registration registration, Set paths) { try { - ResultsAddKeyValueProto results = getParametersFromProfile(registration, paths); + ResultsAddKeyValueProto results = this.getParametersFromProfile(registration, paths); SessionInfoProto sessionInfo = this.getSessionInfoOrCloseSession(registration); if (results != null && sessionInfo != null) { if (results.getResultAttributes().size() > 0) { @@ -1020,8 +1071,6 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler registrationIds.forEach(registrationId -> { Registration registration = clientContext.getRegistration(registrationId); this.readObserveFromProfile(registration, sendAttrToThingsboard.getPathPostParametersAdd(), READ); - // send attr/telemetry to tingsboard for new path -// this.updateAttrTelemetry(registration, sendAttrToThingsboard.getPathPostParametersAdd()); }); } // #4.2 del @@ -1348,7 +1397,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler TransportProtos.GetAttributeRequestMsg getAttributeMsg = adaptor.convertToGetAttributes(null, keyNamesMap.values()); transportService.process(sessionInfo, getAttributeMsg, getAckCallback(lwM2MClient, getAttributeMsg.getRequestId(), DEVICE_ATTRIBUTES_REQUEST)); } catch (AdaptorException e) { - log.warn("Failed to decode get attributes request", e); + log.trace("Failed to decode get attributes request", e); } } @@ -1369,7 +1418,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler 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); + lwM2MClient.getFwUpdate().sendReadObserveInfo(serviceImpl); } else { log.trace("Firmware [{}] [{}]", lwM2MClient.getDeviceName(), response.getResponseStatus().toString()); } @@ -1377,7 +1426,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler @Override public void onError(Throwable e) { - log.warn("Failed to process firmwareUpdate ", e); + log.trace("Failed to process firmwareUpdate ", e); } }); } @@ -1398,7 +1447,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler 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); + lwM2MClient.getSwUpdate().sendReadObserveInfo(serviceImpl); } else { log.trace("Software [{}] [{}]", lwM2MClient.getDeviceName(), response.getResponseStatus().toString()); } @@ -1448,4 +1497,8 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler objectId != null && objectVer != null && objectVer.equals(lwM2mClient.getRegistration().getSupportedVersion(objectId))); } + public LwM2MTransportServerConfig getConfig() { + return this.config; + } + } 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 ed7242ad0d..e23d55f3a1 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 @@ -117,7 +117,6 @@ 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(); 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 a93e969a3d..93424b44e5 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 @@ -86,7 +86,7 @@ public class LwM2mServerListener { @Override public void cancelled(Observation observation) { - String msg = String.format("%s: Cancel Observation %s.", LOG_LW2M_INFO, observation.getPath()); + String msg = String.format("%s: Canceled Observation %s.", LOG_LW2M_INFO, observation.getPath()); service.sendLogsToThingsboard(msg, observation.getRegistrationId()); log.warn(msg); } @@ -94,13 +94,14 @@ public class LwM2mServerListener { @Override public void onResponse(Observation observation, Registration registration, ObserveResponse response) { if (registration != null) { - try { - service.onUpdateValueAfterReadResponse(registration, convertPathFromObjectIdToIdVer(observation.getPath().toString(), - registration), response, null); - } catch (Exception e) { - log.error("Observation/Read onResponse", e); - - } +// if (observation.getPath().isResource() || observation.getPath().isResourceInstance()) { +// String msg = String.format("%s: Successful Observation %s.", LOG_LW2M_INFO, +// observation.getPath()); +// log.warn(msg); +// service.sendLogsToThingsboard(msg, registration.getId()); +// } + service.onUpdateValueAfterReadResponse(registration, convertPathFromObjectIdToIdVer(observation.getPath().toString(), + registration), response, null); } } @@ -113,9 +114,8 @@ public class LwM2mServerListener { public void newObservation(Observation observation, Registration registration) { String msg = String.format("%s: Successful start newObservation %s.", LOG_LW2M_INFO, observation.getPath()); + log.warn(msg); service.sendLogsToThingsboard(msg, registration.getId()); - log.trace(msg); } }; - } diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportMsgHandler.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportMsgHandler.java index bb0be3aa36..794df65db5 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportMsgHandler.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportMsgHandler.java @@ -21,6 +21,7 @@ import org.eclipse.leshan.server.registration.Registration; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.DeviceProfile; import org.thingsboard.server.gen.transport.TransportProtos; +import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig; import org.thingsboard.server.transport.lwm2m.server.client.Lwm2mClientRpcRequest; import java.util.Collection; @@ -36,7 +37,7 @@ public interface LwM2mTransportMsgHandler { void onSleepingDev(Registration registration); - void setCancelObservations(Registration registration); + void setCancelObservationsAll(Registration registration); void onUpdateValueAfterReadResponse(Registration registration, String path, ReadResponse response, Lwm2mClientRpcRequest rpcRequest); @@ -63,4 +64,6 @@ public interface LwM2mTransportMsgHandler { void onAwakeDev(Registration registration); void sendLogsToThingsboard(String msg, String registrationId); + + LwM2MTransportServerConfig getConfig(); } 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 34dffaa29d..425f1ee020 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 @@ -36,7 +36,6 @@ import org.eclipse.leshan.core.request.ObserveRequest; import org.eclipse.leshan.core.request.ReadRequest; import org.eclipse.leshan.core.request.WriteRequest; import org.eclipse.leshan.core.request.exception.ClientSleepingException; -import org.eclipse.leshan.core.response.CancelObservationResponse; import org.eclipse.leshan.core.response.DeleteResponse; import org.eclipse.leshan.core.response.DiscoverResponse; import org.eclipse.leshan.core.response.ExecuteResponse; @@ -49,7 +48,6 @@ 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; @@ -70,16 +68,25 @@ import java.util.stream.Collectors; 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.common.data.firmware.FirmwareUpdateStatus.DOWNLOADED; +import static org.thingsboard.server.common.data.firmware.FirmwareUpdateStatus.FAILED; +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportServerHelper.getContentFormatByResourceModelType; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.DEFAULT_TIMEOUT; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_PACKAGE_ID; +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_UPDATE_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; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.DISCOVER_All; +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.EXECUTE; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.OBSERVE_CANCEL; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.OBSERVE_READ_ALL; -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.RESPONSE_CHANNEL; +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.RESPONSE_REQUEST_CHANNEL; +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SW_INSTALL_ID; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SW_PACKAGE_ID; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertPathFromIdVerToObjectId; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertPathFromObjectIdToIdVer; @@ -90,7 +97,7 @@ import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.c @TbLwM2mTransportComponent @RequiredArgsConstructor public class LwM2mTransportRequest { - private ExecutorService executorResponse; + private ExecutorService responseRequestExecutor; public LwM2mValueConverterImpl converter; @@ -102,8 +109,8 @@ public class LwM2mTransportRequest { @PostConstruct public void init() { this.converter = LwM2mValueConverterImpl.getInstance(); - executorResponse = Executors.newFixedThreadPool(this.config.getResponsePoolSize(), - new NamedThreadFactory(String.format("LwM2M %s channel response", RESPONSE_CHANNEL))); + responseRequestExecutor = Executors.newFixedThreadPool(this.config.getResponsePoolSize(), + new NamedThreadFactory(String.format("LwM2M %s channel response after request", RESPONSE_REQUEST_CHANNEL))); } /** @@ -119,118 +126,14 @@ public class LwM2mTransportRequest { String contentFormatName, Object params, long timeoutInMs, Lwm2mClientRpcRequest rpcRequest) { try { String target = convertPathFromIdVerToObjectId(targetIdVer); - DownlinkRequest request = null; ContentFormat contentFormat = contentFormatName != null ? ContentFormat.fromName(contentFormatName.toUpperCase()) : ContentFormat.DEFAULT; LwM2mClient lwM2MClient = this.lwM2mClientContext.getOrRegister(registration); LwM2mPath resultIds = target != null ? new LwM2mPath(target) : null; if (!OBSERVE_READ_ALL.name().equals(typeOper.name()) && resultIds != null && registration != null && resultIds.getObjectId() >= 0 && lwM2MClient != null) { if (lwM2MClient.isValidObjectVersion(targetIdVer)) { timeoutInMs = timeoutInMs > 0 ? timeoutInMs : DEFAULT_TIMEOUT; - ResourceModel resourceModel = null; - switch (typeOper) { - case READ: - request = new ReadRequest(contentFormat, target); - break; - case DISCOVER: - request = new DiscoverRequest(target); - break; - case OBSERVE: - if (resultIds.isResource()) { - 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) { - request = new ObserveRequest(contentFormat, resultIds.getObjectId()); - } - break; - case OBSERVE_CANCEL: - /* - lwM2MTransportRequest.sendAllRequest(lwServer, registration, path, POST_TYPE_OPER_OBSERVE_CANCEL, null, null, null, null, context.getTimeout()); - At server side this will not remove the observation from the observation store, to do it you need to use - {@code ObservationService#cancelObservation()} - */ - context.getServer().getObservationService().cancelObservations(registration, target); - break; - case EXECUTE: - resourceModel = lwM2MClient.getResourceModel(targetIdVer, this.config - .getModelProvider()); - if (params != null && !resourceModel.multiple) { - request = new ExecuteRequest(target, (String) this.converter.convertValue(params, resourceModel.type, ResourceModel.Type.STRING, resultIds)); - } else { - request = new ExecuteRequest(target); - } - break; - case WRITE_REPLACE: - // Request to write a String Single-Instance Resource using the TLV content format. - resourceModel = lwM2MClient.getResourceModel(targetIdVer, this.config.getModelProvider()); - if (contentFormat.equals(ContentFormat.TLV)) { - request = this.getWriteRequestSingleResource(null, resultIds.getObjectId(), - resultIds.getObjectInstanceId(), resultIds.getResourceId(), params, resourceModel.type, - registration, rpcRequest); - } - // Mode.REPLACE && Request to write a String Single-Instance Resource using the given content format (TEXT, TLV, JSON) - else if (!contentFormat.equals(ContentFormat.TLV)) { - request = this.getWriteRequestSingleResource(contentFormat, resultIds.getObjectId(), - resultIds.getObjectInstanceId(), resultIds.getResourceId(), params, resourceModel.type, - registration, rpcRequest); - } - break; - case WRITE_UPDATE: - if (resultIds.isResource()) { - /** - * send request: path = '/3/0' node == wM2mObjectInstance - * with params == "\"resources\": {15: resource:{id:15. value:'+01'...}} - **/ - Collection resources = lwM2MClient.getNewOneResourceForInstance( - targetIdVer, params, - this.config.getModelProvider(), - this.converter); - request = new WriteRequest(WriteRequest.Mode.UPDATE, contentFormat, resultIds.getObjectId(), - resultIds.getObjectInstanceId(), resources); - } - - /** - * params = "{\"id\":0,\"resources\":[{\"id\":14,\"value\":\"+5\"},{\"id\":15,\"value\":\"+9\"}]}" - * - * int rscId = resultIds.getObjectInstanceId(); - */ - - else if (resultIds.isObjectInstance()) { - if (((ConcurrentHashMap) params).size() > 0) { - Collection resources = lwM2MClient.getNewManyResourcesForInstance( - targetIdVer, params, - this.config.getModelProvider(), - this.converter); - if (resources.size() > 0) { - request = new WriteRequest(WriteRequest.Mode.UPDATE, contentFormat, resultIds.getObjectId(), - resultIds.getObjectInstanceId(), resources); - } else { - Lwm2mClientRpcRequest rpcRequestClone = (Lwm2mClientRpcRequest) rpcRequest.clone(); - if (rpcRequestClone != null) { - String errorMsg = String.format("Path %s params is not valid", targetIdVer); - serviceImpl.sentRpcRequest(rpcRequestClone, BAD_REQUEST.getName(), errorMsg, LOG_LW2M_ERROR); - rpcRequest = null; - } - } - } - } else if (resultIds.getObjectId() >= 0) { - request = new ObserveRequest(resultIds.getObjectId()); - } - break; - case WRITE_ATTRIBUTES: - request = createWriteAttributeRequest(target, params); - break; - case DELETE: - request = new DeleteRequest(target); - break; - } - + DownlinkRequest request = createRequest (registration, lwM2MClient, typeOper, contentFormat, target, + targetIdVer, resultIds, params, rpcRequest); if (request != null) { try { this.sendRequest(registration, lwM2MClient, request, timeoutInMs, rpcRequest); @@ -242,15 +145,19 @@ public class LwM2mTransportRequest { } catch (Exception e) { log.error("[{}] [{}] [{}] Failed to send downlink.", registration.getEndpoint(), targetIdVer, typeOper.name(), e); } - } else if (OBSERVE_CANCEL == typeOper) { - log.trace("[{}], [{}] - [{}] SendRequest", registration.getEndpoint(), typeOper.name(), targetIdVer); - if (rpcRequest != null) { - rpcRequest.setInfoMsg(null); - serviceImpl.sentRpcRequest(rpcRequest, CONTENT.name(), null, null); + } + else if (WRITE_UPDATE.name().equals(typeOper.name())) { + Lwm2mClientRpcRequest rpcRequestClone = (Lwm2mClientRpcRequest) rpcRequest.clone(); + if (rpcRequestClone != null) { + String errorMsg = String.format("Path %s params is not valid", targetIdVer); + serviceImpl.sentRpcRequest(rpcRequestClone, BAD_REQUEST.getName(), errorMsg, LOG_LW2M_ERROR); + rpcRequest = null; } - } else { + } + else if (!OBSERVE_CANCEL.name().equals(typeOper.name())) { log.error("[{}], [{}] - [{}] error SendRequest", registration.getEndpoint(), typeOper.name(), targetIdVer); if (rpcRequest != null) { + ResourceModel resourceModel = lwM2MClient.getResourceModel(targetIdVer, this.config.getModelProvider()); String errorMsg = resourceModel == null ? String.format("Path %s not found in object version", targetIdVer) : "SendRequest - null"; serviceImpl.sentRpcRequest(rpcRequest, NOT_FOUND.getName(), errorMsg, LOG_LW2M_ERROR); } @@ -265,30 +172,140 @@ public class LwM2mTransportRequest { Set observations = context.getServer().getObservationService().getObservations(registration); paths = observations.stream().map(observation -> observation.getPath().toString()).collect(Collectors.toUnmodifiableSet()); } else { + assert registration != null; Link[] objectLinks = registration.getSortedObjectLinks(); - paths = Arrays.stream(objectLinks).map(link -> link.toString()).collect(Collectors.toUnmodifiableSet()); + paths = Arrays.stream(objectLinks).map(Link::toString).collect(Collectors.toUnmodifiableSet()); + String msg = String.format("%s: type operation %s paths - %s", LOG_LW2M_INFO, + typeOper.name(), paths); + serviceImpl.sendLogsToThingsboard(msg, registration.getId()); } - String msg = String.format("%s: type operation %s paths - %s", LOG_LW2M_INFO, - OBSERVE_READ_ALL.type, paths); - serviceImpl.sendLogsToThingsboard(msg, registration.getId()); - log.warn("[{}] [{}], [{}]", typeOper.name(), registration.getEndpoint(), msg); if (rpcRequest != null) { String valueMsg = String.format("Paths - %s", paths); serviceImpl.sentRpcRequest(rpcRequest, CONTENT.name(), valueMsg, LOG_LW2M_VALUE); } + } else if (OBSERVE_CANCEL.name().equals(typeOper.name())) { + int observeCancelCnt = context.getServer().getObservationService().cancelObservations(registration); + String observeCancelMsgAll = String.format("%s: type operation %s paths: All count: %d", LOG_LW2M_INFO, + OBSERVE_CANCEL.name(), observeCancelCnt); + this.afterObserveCancel(registration, observeCancelCnt, observeCancelMsgAll, rpcRequest); } } catch (Exception e) { String msg = String.format("%s: type operation %s %s", LOG_LW2M_ERROR, typeOper.name(), e.getMessage()); serviceImpl.sendLogsToThingsboard(msg, registration.getId()); - try { - throw new Exception(e); - } catch (Exception exception) { - exception.printStackTrace(); + if (rpcRequest != null) { + String errorMsg = String.format("Path %s type operation %s %s", targetIdVer, typeOper.name(), e.getMessage()); + serviceImpl.sentRpcRequest(rpcRequest, NOT_FOUND.getName(), errorMsg, LOG_LW2M_ERROR); } } } + private DownlinkRequest createRequest (Registration registration, LwM2mClient lwM2MClient, LwM2mTypeOper typeOper, + ContentFormat contentFormat, String target, String targetIdVer, + LwM2mPath resultIds, Object params, Lwm2mClientRpcRequest rpcRequest) { + DownlinkRequest request = null; + switch (typeOper) { + case READ: + request = new ReadRequest(contentFormat, target); + break; + case DISCOVER: + request = new DiscoverRequest(target); + break; + case OBSERVE: + String msg = String.format("%s: Send Observation %s.", LOG_LW2M_INFO, targetIdVer); + log.warn(msg); + if (resultIds.isResource()) { + 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) { + request = new ObserveRequest(contentFormat, resultIds.getObjectId()); + } + break; + case OBSERVE_CANCEL: + /* + lwM2MTransportRequest.sendAllRequest(lwServer, registration, path, POST_TYPE_OPER_OBSERVE_CANCEL, null, null, null, null, context.getTimeout()); + At server side this will not remove the observation from the observation store, to do it you need to use + {@code ObservationService#cancelObservation()} + */ + int observeCancelCnt = context.getServer().getObservationService().cancelObservations(registration, target); + String observeCancelMsg = String.format("%s: type operation %s paths: %s count: %d", LOG_LW2M_INFO, + OBSERVE_CANCEL.name(), target, observeCancelCnt); + this.afterObserveCancel(registration, observeCancelCnt, observeCancelMsg, rpcRequest); + break; + case EXECUTE: + ResourceModel resourceModelExe = lwM2MClient.getResourceModel(targetIdVer, this.config.getModelProvider()); + if (params != null && !resourceModelExe.multiple) { + request = new ExecuteRequest(target, (String) this.converter.convertValue(params, resourceModelExe.type, ResourceModel.Type.STRING, resultIds)); + } else { + request = new ExecuteRequest(target); + } + break; + case WRITE_REPLACE: + /** + * Request to write a String Single-Instance Resource using the TLV content format. + * Type from resourceModel -> STRING, INTEGER, FLOAT, BOOLEAN, OPAQUE, TIME, OBJLNK + * contentFormat -> TLV, TLV, TLV, TLV, OPAQUE, TLV, LINK + * JSON, TEXT; + **/ + ResourceModel resourceModelWrite = lwM2MClient.getResourceModel(targetIdVer, this.config.getModelProvider()); + contentFormat = getContentFormatByResourceModelType(resourceModelWrite, contentFormat); + request = this.getWriteRequestSingleResource(contentFormat, resultIds.getObjectId(), + resultIds.getObjectInstanceId(), resultIds.getResourceId(), params, resourceModelWrite.type, + registration, rpcRequest); + break; + case WRITE_UPDATE: + if (resultIds.isResource()) { + /** + * send request: path = '/3/0' node == wM2mObjectInstance + * with params == "\"resources\": {15: resource:{id:15. value:'+01'...}} + **/ + Collection resources = lwM2MClient.getNewResourceForInstance( + targetIdVer, params, + this.config.getModelProvider(), + this.converter); + contentFormat = getContentFormatByResourceModelType(lwM2MClient.getResourceModel(targetIdVer, this.config.getModelProvider()), + contentFormat); + request = new WriteRequest(WriteRequest.Mode.UPDATE, contentFormat, resultIds.getObjectId(), + resultIds.getObjectInstanceId(), resources); + } + /** + * params = "{\"id\":0,\"resources\":[{\"id\":14,\"value\":\"+5\"},{\"id\":15,\"value\":\"+9\"}]}" + * int rscId = resultIds.getObjectInstanceId(); + * contentFormat – Format of the payload (TLV or JSON). + */ + else if (resultIds.isObjectInstance()) { + if (((ConcurrentHashMap) params).size() > 0) { + Collection resources = lwM2MClient.getNewResourcesForInstance( + targetIdVer, params, + this.config.getModelProvider(), + this.converter); + if (resources.size() > 0) { + contentFormat = contentFormat.equals(ContentFormat.JSON) ? contentFormat : ContentFormat.TLV; + request = new WriteRequest(WriteRequest.Mode.UPDATE, contentFormat, resultIds.getObjectId(), + resultIds.getObjectInstanceId(), resources); + } + } + } else if (resultIds.getObjectId() >= 0) { + request = new ObserveRequest(resultIds.getObjectId()); + } + break; + case WRITE_ATTRIBUTES: + request = createWriteAttributeRequest(target, params); + break; + case DELETE: + request = new DeleteRequest(target); + break; + } + return request; + } + /** * @param registration - * @param request - @@ -314,6 +331,7 @@ public class LwM2mTransportRequest { if (!lwM2MClient.isInit()) { lwM2MClient.initReadValue(this.serviceImpl, convertPathFromObjectIdToIdVer(request.getPath().toString(), registration)); } + /** Not Found */ if (rpcRequest != null) { serviceImpl.sentRpcRequest(rpcRequest, response.getCode().getName(), response.getErrorMessage(), LOG_LW2M_ERROR); } @@ -322,7 +340,15 @@ public class LwM2mTransportRequest { **/ if (lwM2MClient.getFwUpdate().isInfoFwSwUpdate()) { lwM2MClient.getFwUpdate().initReadValue(serviceImpl, request.getPath().toString()); - log.warn("updateFirmwareClient1"); + } + if (lwM2MClient.getSwUpdate().isInfoFwSwUpdate()) { + lwM2MClient.getSwUpdate().initReadValue(serviceImpl, request.getPath().toString()); + } + if (request.getPath().toString().equals(FW_PACKAGE_ID) || request.getPath().toString().equals(SW_PACKAGE_ID)) { + this.afterWriteFwSWUpdateError(registration, request, response.getErrorMessage()); + } + if (request.getPath().toString().equals(FW_UPDATE_ID) || request.getPath().toString().equals(SW_INSTALL_ID)) { + this.afterExecuteFwSwUpdateError(registration, request, response.getErrorMessage()); } } }, e -> { @@ -331,7 +357,15 @@ public class LwM2mTransportRequest { **/ if (lwM2MClient.getFwUpdate().isInfoFwSwUpdate()) { lwM2MClient.getFwUpdate().initReadValue(serviceImpl, request.getPath().toString()); - log.warn("updateFirmwareClient2"); + } + if (lwM2MClient.getSwUpdate().isInfoFwSwUpdate()) { + lwM2MClient.getSwUpdate().initReadValue(serviceImpl, request.getPath().toString()); + } + if (request.getPath().toString().equals(FW_PACKAGE_ID) || request.getPath().toString().equals(SW_PACKAGE_ID)) { + this.afterWriteFwSWUpdateError(registration, request, e.getMessage()); + } + if (request.getPath().toString().equals(FW_UPDATE_ID) || request.getPath().toString().equals(SW_INSTALL_ID)) { + this.afterExecuteFwSwUpdateError(registration, request, e.getMessage()); } if (!lwM2MClient.isInit()) { lwM2MClient.initReadValue(this.serviceImpl, convertPathFromObjectIdToIdVer(request.getPath().toString(), registration)); @@ -395,7 +429,7 @@ public class LwM2mTransportRequest { private void handleResponse(Registration registration, final String path, LwM2mResponse response, DownlinkRequest request, Lwm2mClientRpcRequest rpcRequest) { - executorResponse.submit(() -> { + responseRequestExecutor.submit(() -> { try { this.sendResponse(registration, path, response, request, rpcRequest); } catch (Exception e) { @@ -414,28 +448,26 @@ public class LwM2mTransportRequest { private void sendResponse(Registration registration, String path, LwM2mResponse response, DownlinkRequest request, Lwm2mClientRpcRequest rpcRequest) { String pathIdVer = convertPathFromObjectIdToIdVer(path, registration); + String msgLog = ""; if (response instanceof ReadResponse) { serviceImpl.onUpdateValueAfterReadResponse(registration, pathIdVer, (ReadResponse) response, rpcRequest); - } else if (response instanceof CancelObservationResponse) { - log.info("[{}] Path [{}] CancelObservationResponse 3_Send", pathIdVer, response); - } else if (response instanceof DeleteResponse) { - log.info("[{}] Path [{}] DeleteResponse 5_Send", pathIdVer, response); + log.warn("[{}] Path [{}] DeleteResponse 5_Send", pathIdVer, response); } else if (response instanceof DiscoverResponse) { - log.info("[{}] [{}] - [{}] [{}] Discovery value: [{}]", registration.getEndpoint(), - ((Response) response.getCoapResponse()).getCode(), response.getCode(), - request.getPath().toString(), ((DiscoverResponse) response).getObjectLinks()); + String discoverValue = Link.serialize(((DiscoverResponse)response).getObjectLinks()); + msgLog = String.format("%s: type operation: %s path: %s value: %s", + LOG_LW2M_INFO, DISCOVER.name(), request.getPath().toString(), discoverValue); + serviceImpl.sendLogsToThingsboard(msgLog, registration.getId()); + log.warn("DiscoverResponse: [{}]", (DiscoverResponse) response); if (rpcRequest != null) { - String discoveryMsg = String.format("%s", - Arrays.stream(((DiscoverResponse) response).getObjectLinks()).collect(Collectors.toSet())); - serviceImpl.sentRpcRequest(rpcRequest, response.getCode().getName(), discoveryMsg, LOG_LW2M_VALUE); + serviceImpl.sentRpcRequest(rpcRequest, response.getCode().getName(), discoverValue, LOG_LW2M_VALUE); } } else if (response instanceof ExecuteResponse) { - log.info("[{}] Path [{}] ExecuteResponse 7_Send", pathIdVer, response); + log.warn("[{}] Path [{}] ExecuteResponse 7_Send", pathIdVer, response); } else if (response instanceof WriteAttributesResponse) { - log.info("[{}] Path [{}] WriteAttributesResponse 8_Send", pathIdVer, response); + log.warn("[{}] Path [{}] WriteAttributesResponse 8_Send", pathIdVer, response); } else if (response instanceof WriteResponse) { - log.info("[{}] Path [{}] WriteResponse 9_Send", pathIdVer, response); + log.warn("[{}] Path [{}] WriteResponse 9_Send", pathIdVer, response); this.infoWriteResponse(registration, response, request); serviceImpl.onWriteResponseOk(registration, pathIdVer, (WriteRequest) request); } @@ -480,9 +512,8 @@ public class LwM2mTransportRequest { } if (msg != null) { serviceImpl.sendLogsToThingsboard(msg, registration.getId()); - log.warn(msg); if (request.getPath().toString().equals(FW_PACKAGE_ID) || request.getPath().toString().equals(SW_PACKAGE_ID)) { - this.executeFwSwUpdate(registration, request); + this.afterWriteSuccessFwSwUpdate(registration, request); } } } catch (Exception e) { @@ -490,15 +521,54 @@ public class LwM2mTransportRequest { } } - 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(); + /** + * After finish operation FwSwUpdate Write (success): + * fw_state/sw_state = DOWNLOADED + * send operation Execute + */ + private void afterWriteSuccessFwSwUpdate(Registration registration, DownlinkRequest request) { + LwM2mClient lwM2MClient = this.lwM2mClientContext.getClientByRegistrationId(registration.getId()); + if (request.getPath().toString().equals(FW_PACKAGE_ID) && lwM2MClient.getFwUpdate() != null) { + lwM2MClient.getFwUpdate().setStateUpdate(DOWNLOADED.name()); + lwM2MClient.getFwUpdate().sendLogs(WRITE_REPLACE.name(), LOG_LW2M_INFO, null); } - if (request.getPath().toString().equals(SW_PACKAGE_ID) - && FirmwareUpdateStatus.DOWNLOADING.name().equals(lwM2mClient.getSwUpdate().getStateUpdate())) { - lwM2mClient.getSwUpdate().sendReadInfoForWrite(); + if (request.getPath().toString().equals(SW_PACKAGE_ID) && lwM2MClient.getSwUpdate() != null) { + lwM2MClient.getSwUpdate().setStateUpdate(DOWNLOADED.name()); + lwM2MClient.getSwUpdate().sendLogs(WRITE_REPLACE.name(), LOG_LW2M_INFO, null); + } + } + + /** + * After finish operation FwSwUpdate Write (error): fw_state = FAILED + */ + private void afterWriteFwSWUpdateError(Registration registration, DownlinkRequest request, String msgError) { + LwM2mClient lwM2MClient = this.lwM2mClientContext.getClientByRegistrationId(registration.getId()); + if (request.getPath().toString().equals(FW_PACKAGE_ID) && lwM2MClient.getFwUpdate() != null) { + lwM2MClient.getFwUpdate().setStateUpdate(FAILED.name()); + lwM2MClient.getFwUpdate().sendLogs(WRITE_REPLACE.name(), LOG_LW2M_ERROR, msgError); + } + if (request.getPath().toString().equals(SW_PACKAGE_ID) && lwM2MClient.getSwUpdate() != null) { + lwM2MClient.getSwUpdate().setStateUpdate(FAILED.name()); + lwM2MClient.getSwUpdate().sendLogs(WRITE_REPLACE.name(), LOG_LW2M_ERROR, msgError); + } + } + + private void afterExecuteFwSwUpdateError(Registration registration, DownlinkRequest request, String msgError) { + LwM2mClient lwM2MClient = this.lwM2mClientContext.getClientByRegistrationId(registration.getId()); + if (request.getPath().toString().equals(FW_UPDATE_ID) && lwM2MClient.getFwUpdate() != null) { + lwM2MClient.getFwUpdate().sendLogs(EXECUTE.name(), LOG_LW2M_ERROR, msgError); + } + if (request.getPath().toString().equals(SW_INSTALL_ID) && lwM2MClient.getSwUpdate() != null) { + lwM2MClient.getSwUpdate().sendLogs(EXECUTE.name(), LOG_LW2M_ERROR, msgError); + } + } + + private void afterObserveCancel(Registration registration, int observeCancelCnt, String observeCancelMsg, Lwm2mClientRpcRequest rpcRequest) { + serviceImpl.sendLogsToThingsboard(observeCancelMsg, registration.getId()); + log.warn("[{}]", observeCancelMsg); + if (rpcRequest != null) { + rpcRequest.setInfoMsg(String.format("Count: %d", observeCancelCnt)); + serviceImpl.sentRpcRequest(rpcRequest, CONTENT.name(), null, LOG_LW2M_INFO); } } } diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportServerHelper.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportServerHelper.java index 79902348a9..6b9049ccf6 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportServerHelper.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportServerHelper.java @@ -38,6 +38,7 @@ import org.eclipse.leshan.core.model.InvalidDDFFileException; import org.eclipse.leshan.core.model.ObjectModel; import org.eclipse.leshan.core.model.ResourceModel; import org.eclipse.leshan.core.node.codec.CodecException; +import org.eclipse.leshan.core.request.ContentFormat; import org.springframework.stereotype.Component; import org.thingsboard.server.common.transport.TransportServiceCallback; import org.thingsboard.server.gen.transport.TransportProtos; @@ -53,7 +54,6 @@ import java.util.ArrayList; import java.util.List; import static org.thingsboard.server.gen.transport.TransportProtos.KeyValueType.BOOLEAN_V; -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_TELEMETRY; @Slf4j @Component @@ -68,7 +68,7 @@ public class LwM2mTransportServerHelper { * send to Thingsboard Attribute || Telemetry * * @param msg - JsonObject: [{name: value}] - * @return - dummy + * @return - dummyWriteReplace {\"targetIdVer\":\"/19_1.0/0/0\",\"value\":0082} */ private TransportServiceCallback getPubAckCallbackSendAttrTelemetry(final T msg) { return new TransportServiceCallback<>() { @@ -135,16 +135,16 @@ public class LwM2mTransportServerHelper { } /** - * - * @param logMsg - info about Logs + * @param value - info about Logs * @return- KeyValueProto for telemetry (Logs) */ - public List getKvLogyToThingsboard(String logMsg) { + public List getKvStringtoThingsboard(String key, String value) { List result = new ArrayList<>(); + value = value.replaceAll("<", "").replaceAll(">", ""); result.add(TransportProtos.KeyValueProto.newBuilder() - .setKey(LOG_LW2M_TELEMETRY) + .setKey(key) .setType(TransportProtos.KeyValueType.STRING_V) - .setStringV(logMsg).build()); + .setStringV(value).build()); return result; } @@ -180,8 +180,7 @@ public class LwM2mTransportServerHelper { } /** - * - * @param currentType - + * @param currentType - * @param resourcePath - * @return */ @@ -203,6 +202,28 @@ public class LwM2mTransportServerHelper { throw new CodecException("Invalid ResourceModel_Type for resource %s, got %s", resourcePath, currentType); } + public static ContentFormat convertResourceModelTypeToContentFormat(ResourceModel.Type type) { + switch (type) { + case BOOLEAN: + case STRING: + case TIME: + case INTEGER: + case FLOAT: + return ContentFormat.TLV; + case OPAQUE: + return ContentFormat.OPAQUE; + case OBJLNK: + return ContentFormat.LINK; + default: + } + throw new CodecException("Invalid ResourceModel_Type for %s ContentFormat.", type); + } + + public static ContentFormat getContentFormatByResourceModelType(ResourceModel resourceModel, ContentFormat contentFormat) { + return contentFormat.equals(ContentFormat.TLV) ? convertResourceModelTypeToContentFormat(resourceModel.type) : + contentFormat; + } + public static Object getValueFromKvProto(TransportProtos.KeyValueProto kv) { switch (kv.getType()) { case BOOLEAN_V: 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 53881ac2c7..4386caebc7 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 @@ -104,7 +104,8 @@ public class LwM2mTransportUtil { public static final long DEFAULT_TIMEOUT = 2 * 60 * 1000L; // 2min in ms - public static final String LOG_LW2M_TELEMETRY = "logLwm2m"; + public static final String + LOG_LW2M_TELEMETRY = "logLwm2m"; public static final String LOG_LW2M_INFO = "info"; public static final String LOG_LW2M_ERROR = "error"; public static final String LOG_LW2M_WARN = "warn"; @@ -208,8 +209,13 @@ public class LwM2mTransportUtil { DELETE(10, "Delete"), // only for RPC - READ_INFO_FW(11, "ReadInfoFirmware"), - READ_INFO_SW(12, "ReadInfoSoftware"); + FW_READ_INFO(11, "FirmwareReadInfo"), + FW_UPDATE(12, "FirmwareUpdate"), + FW_UPDATE_URL(14, "FirmwareUpdateUrl"), + SW_READ_INFO(15, "SoftwareReadInfo"), + SW_UPDATE(16, "SoftwareUpdate"), + SW_UPDATE_URL(17, "SoftwareUpdateUrl"), + SW_UNINSTALL(18, "SoftwareUninstall"); public int code; public String type; @@ -357,7 +363,7 @@ public class LwM2mTransportUtil { } /** - * Update State R + * SW 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) @@ -429,7 +435,7 @@ public class LwM2mTransportUtil { 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), + SUCCESSFULLY_DOWNLOADED_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), @@ -489,7 +495,7 @@ public class LwM2mTransportUtil { return DOWNLOADING; case SUCCESSFULLY_INSTALLED: return UPDATED; - case SUCCESSFULLY_INSTALLED_VERIFIED: + case SUCCESSFULLY_DOWNLOADED_VERIFIED: return VERIFIED; case NOT_ENOUGH_STORAGE: case OUT_OFF_MEMORY: @@ -507,7 +513,9 @@ public class LwM2mTransportUtil { } public static final String EVENT_AWAKE = "AWAKE"; + public static final String RESPONSE_REQUEST_CHANNEL = "RESP_REQ"; public static final String RESPONSE_CHANNEL = "RESP"; + public static final String OBSERVE_CHANNEL = "OBSERVE"; public static boolean equalsResourceValue(Object valueOld, Object valueNew, ResourceModel.Type type, LwM2mPath resourcePath) throws CodecException { diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mVersionedModelProvider.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mVersionedModelProvider.java index 800c518adc..2d981e0d4e 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mVersionedModelProvider.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mVersionedModelProvider.java @@ -82,7 +82,7 @@ public class LwM2mVersionedModelProvider implements LwM2mModelProvider { if (objectModel != null) return objectModel.resources.get(resourceId); else - log.warn("TbResources (Object model) with id [{}/0/{}] not found on the server", objectId, resourceId); + log.trace("TbResources (Object model) with id [{}/0/{}] not found on the server", objectId, resourceId); return null; } catch (Exception e) { log.error("", e); diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/adaptors/LwM2MJsonAdaptor.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/adaptors/LwM2MJsonAdaptor.java index 65a1e14a4c..9c192ae801 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/adaptors/LwM2MJsonAdaptor.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/adaptors/LwM2MJsonAdaptor.java @@ -64,7 +64,6 @@ public class LwM2MJsonAdaptor implements LwM2MTransportAdaptor { } return result.build(); } catch (RuntimeException e) { - log.warn("Failed to decode get attributes request", e); throw new AdaptorException(e); } } 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 4e91bb1d50..1969bbe84c 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 @@ -18,7 +18,11 @@ package org.thingsboard.server.transport.lwm2m.server.client; import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; +import org.eclipse.leshan.core.model.ObjectModel; import org.eclipse.leshan.core.model.ResourceModel; +import org.eclipse.leshan.core.node.LwM2mMultipleResource; +import org.eclipse.leshan.core.node.LwM2mObject; +import org.eclipse.leshan.core.node.LwM2mObjectInstance; import org.eclipse.leshan.core.node.LwM2mPath; import org.eclipse.leshan.core.node.LwM2mResource; import org.eclipse.leshan.core.node.LwM2mSingleResource; @@ -47,6 +51,8 @@ import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.CopyOnWriteArrayList; import java.util.stream.Collectors; +import static org.eclipse.leshan.core.model.ResourceModel.Type.OPAQUE; +import static org.eclipse.leshan.core.model.ResourceModel.Type.STRING; 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; @@ -192,6 +198,14 @@ public class LwM2mClient implements Cloneable { return null; } + public Object getResourceName (String pathRezIdVer, String pathRezId) { + String pathRez = pathRezIdVer == null ? convertPathFromObjectIdToIdVer(pathRezId, this.registration) : pathRezIdVer; + if (this.resources.get(pathRez) != null) { + return this.resources.get(pathRez).getResourceModel().name; + } + return null; + } + public ResourceModel getResourceModel(String pathIdVer, LwM2mModelProvider modelProvider) { LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(pathIdVer)); String verSupportedObject = registration.getSupportedObject().get(pathIds.getObjectId()); @@ -200,8 +214,55 @@ public class LwM2mClient implements Cloneable { .getResourceModel(pathIds.getObjectId(), pathIds.getResourceId()) : null; } - public Collection getNewOneResourceForInstance(String pathRezIdVer, Object params, LwM2mModelProvider modelProvider, - LwM2mValueConverterImpl converter) { + public ObjectModel getObjectModel(String pathIdVer, LwM2mModelProvider modelProvider) { + LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(pathIdVer)); + String verSupportedObject = registration.getSupportedObject().get(pathIds.getObjectId()); + String verRez = getVerFromPathIdVerOrId(pathIdVer); + return verRez == null || verRez.equals(verSupportedObject) ? modelProvider.getObjectModel(registration) + .getObjectModel(pathIds.getObjectId()) : null; + } + + public String objectToString (LwM2mObject lwM2mObject, LwM2mValueConverterImpl converter, String pathIdVer) { + StringBuilder builder = new StringBuilder(); + builder.append("LwM2mObject [id=").append(lwM2mObject.getId()).append(", instances={"); + lwM2mObject.getInstances().forEach((instId, inst) -> { + builder.append(instId).append("=").append(this.instanceToString(inst, converter, pathIdVer)).append(", "); + }); + int startInd = builder.lastIndexOf(", "); + if (startInd > 0) { + builder.delete(startInd, startInd + 2); + } + builder.append("}]"); + return builder.toString(); + } + public String instanceToString (LwM2mObjectInstance objectInstance, LwM2mValueConverterImpl converter, String pathIdVer) { + StringBuilder builder = new StringBuilder(); + builder.append("LwM2mObjectInstance [id=").append(objectInstance.getId()).append(", resources={"); + objectInstance.getResources().forEach((resId, res) -> { + builder.append(resId).append("=").append(this.resourceToString (res, converter, pathIdVer)).append(", "); + }); + int startInd = builder.lastIndexOf(", "); + if (startInd > 0) { + builder.delete(startInd, startInd + 2); + } + builder.append("}]"); + return builder.toString(); + } + + public String resourceToString (LwM2mResource lwM2mResource, LwM2mValueConverterImpl converter, String pathIdVer) { + if (!OPAQUE.equals(lwM2mResource.getType())) { + return lwM2mResource.isMultiInstances() ? ((LwM2mMultipleResource) lwM2mResource).toString() : + ((LwM2mSingleResource) lwM2mResource).toString(); + } + else { + return String.format("LwM2mSingleResource [id=%s, value=%s, type=%s]", lwM2mResource.getId(), + converter.convertValue(lwM2mResource.getValue(), + OPAQUE, STRING, new LwM2mPath(convertPathFromIdVerToObjectId(pathIdVer))), lwM2mResource.getType().name()); + } + } + + public Collection getNewResourceForInstance(String pathRezIdVer, Object params, LwM2mModelProvider modelProvider, + LwM2mValueConverterImpl converter) { LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(pathRezIdVer)); Collection resources = ConcurrentHashMap.newKeySet(); Map resourceModels = modelProvider.getObjectModel(registration) @@ -215,8 +276,8 @@ public class LwM2mClient implements Cloneable { return resources; } - public Collection getNewManyResourcesForInstance(String pathRezIdVer, Object params, LwM2mModelProvider modelProvider, - LwM2mValueConverterImpl converter) { + public Collection getNewResourcesForInstance(String pathRezIdVer, Object params, LwM2mModelProvider modelProvider, + LwM2mValueConverterImpl converter) { LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(pathRezIdVer)); Collection resources = ConcurrentHashMap.newKeySet(); Map resourceModels = modelProvider.getObjectModel(registration) 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 index 38c918ed4d..e2bfdbcc2e 100644 --- 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 @@ -34,6 +34,7 @@ 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.FirmwareUpdateStatus.UPDATING; 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; @@ -42,10 +43,10 @@ import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.F 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_ERROR; 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; @@ -56,6 +57,7 @@ import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.S 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; +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.splitCamelCaseString; @Slf4j public class LwM2mFwSwUpdate { @@ -111,7 +113,7 @@ public class LwM2mFwSwUpdate { } private void initPathId() { - if (this.type.equals(FIRMWARE)) { + if (FIRMWARE.equals(this.type) ) { this.pathPackageId = FW_PACKAGE_ID; this.pathStateId = FW_STATE_ID; this.pathResultId = FW_RESULT_ID; @@ -119,7 +121,7 @@ public class LwM2mFwSwUpdate { this.pathVerId = FW_VER_ID; this.pathInstallId = FW_UPDATE_ID; this.wUpdate = FW_UPDATE; - } else if (this.type.equals(SOFTWARE)) { + } else if (SOFTWARE.equals(this.type) ) { this.pathPackageId = SW_PACKAGE_ID; this.pathStateId = SW_UPDATE_STATE_ID; this.pathResultId = SW_RESULT_ID; @@ -142,25 +144,20 @@ public class LwM2mFwSwUpdate { 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()); } } } } + /** + * Send FsSw to Lwm2mClient: + * before operation Write: fw_state = DOWNLOADING + */ private void writeFwSwWare() { + this.stateUpdate = FirmwareUpdateStatus.DOWNLOADING.name(); +// this.observeStateUpdate(); + this.sendLogs(WRITE_REPLACE.name(), LOG_LW2M_INFO, null); int chunkSize = 0; int chunk = 0; byte[] firmwareChunk = this.serviceImpl.firmwareDataCache.get(this.currentId.toString(), chunkSize, chunk); @@ -169,124 +166,155 @@ public class LwM2mFwSwUpdate { firmwareChunk, this.serviceImpl.config.getTimeout(), null); } - public void sendLogs(String typeOper) { + public void sendLogs(String typeOper, String typeInfo, String msgError) { this.sendSateOnThingsboard(); - String msg = String.format("%s: %s, %s, pkgVer: %s: pkgName - %s.", - LOG_LW2M_INFO, this.wUpdate, typeOper, this.currentVersion, this.currentTitle); + String msg = String.format("%s: %s, %s, pkgVer: %s: pkgName - %s state - %s.", + typeInfo, this.wUpdate, typeOper, this.currentVersion, this.currentTitle, this.stateUpdate); + if (LOG_LW2M_ERROR.equals(typeInfo)) { + msg = String.format("%s Error: %s", msg, msgError); + } 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 = "" - Это означает что апдейта еще не было. + * After inspection Update Result + * fw_state/sw_state = UPDATING + * send execute + */ + public void executeFwSwWare() { + this.setStateUpdate(UPDATING.name()); + this.sendLogs(EXECUTE.name(), LOG_LW2M_INFO, null); + this.serviceImpl.lwM2mTransportRequest.sendAllRequest(this.lwM2MClient.getRegistration(), this.pathInstallId, EXECUTE, ContentFormat.TLV.getName(), + null, 0, null); + } + + + /** + * Firmware start: + * -- Если Update Result -errors (более 1) - Это означает что пред. апдейт не прошел. + * - Запускаем апдейт в независимости от состяния прошивки и ее версии. + * -- Если Update Result - не errors (менее или равно 1) и ver не пустой - Это означает что пред. апдейт прошел. + * -- Если Update Result - не errors и 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()) + (updateResultFw <= LwM2mTransportUtil.UpdateResultFw.UPDATE_SUCCESSFULLY.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))) ) ); -// if (condFwUpdateStart) { -// this.sendSateOnThingsboard(stateFw, updateResultFw, pkgName); -// } -// return condFwUpdateStart; } - private boolean conditionalFwUpdateExecute() { - Long state = (Long) this.lwM2MClient.getResourceValue(null, this.pathStateId); + + /** + * Before operation Execute inspection Update Result : + * 0 - Initial value + */ + public boolean conditionalFwExecuteStart() { Long updateResult = (Long) this.lwM2MClient.getResourceValue(null, this.pathResultId); - // #1/#2 - return updateResult == LwM2mTransportUtil.UpdateResultFw.INITIAL.code && state == LwM2mTransportUtil.StateFw.DOWNLOADED.code; + return LwM2mTransportUtil.UpdateResultFw.INITIAL.code == updateResult; } /** - * 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 + * After operation Execute success inspection Update Result : + * 1 - "Firmware updated successfully" + */ + public boolean conditionalFwExecuteAfterSuccess() { + Long updateResult = (Long) this.lwM2MClient.getResourceValue(null, this.pathResultId); + return LwM2mTransportUtil.UpdateResultFw.UPDATE_SUCCESSFULLY.code == updateResult; + } + + /** + * After operation Execute success inspection Update Result : + * > 1 error: "Firmware updated successfully" + */ + public boolean conditionalFwExecuteAfterError() { + Long updateResult = (Long) this.lwM2MClient.getResourceValue(null, this.pathResultId); + return LwM2mTransportUtil.UpdateResultFw.UPDATE_SUCCESSFULLY.code < updateResult; + } + + /** + * Software start + * -- Если Update Result -errors (равно и более 50) - Это означает что пред. апдейт не прошел. + * * - Запускаем апдейт в независимости от состяния прошивки и ее версии. + * -- Если Update Result - не errors (менее 50) и ver не пустой - Это означает что пред. апдейт прошел. + * -- Если Update Result - не errors и ver пустой - Это означает что апдейта еще не было или пред. апдейт UnInstall + * -- Если Update Result - не errors и ver не пустой - Это означает что пред. апдейт 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); + Long updateResultSw = (Long) this.lwM2MClient.getResourceValue(null, this.pathResultId); // #1/#2 - return updateResult > LwM2mTransportUtil.UpdateResultSw.SUCCESSFULLY_INSTALLED_VERIFIED.code || + return updateResultSw >= LwM2mTransportUtil.UpdateResultSw.NOT_ENOUGH_STORAGE.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) + (updateResultSw <= LwM2mTransportUtil.UpdateResultSw.NOT_ENOUGH_STORAGE.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); + /** + * Before operation Execute inspection Update Result : + * 3 - Successfully Downloaded and package integrity verified + */ + public boolean conditionalSwUpdateExecute() { 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; + return LwM2mTransportUtil.UpdateResultSw.SUCCESSFULLY_DOWNLOADED_VERIFIED.code == updateResult; + } + + /** + * After finish operation Execute (success): + * -- inspection Update Result: + * ---- FW если Update Result == 1 ("Firmware updated successfully") или SW если Update Result == 2 ("Software successfully installed.") + * -- fw_state/sw_state = UPDATED + * + * After finish operation Execute (error): + * -- inspection updateResult and send to thingsboard info about error + * --- send to telemetry ( key - this is name Update Result in model) ( + * -- fw_state/sw_state = FAILED + */ + public void finishFwSwUpdate(boolean success) { + Long updateResult = (Long) this.lwM2MClient.getResourceValue(null, this.pathResultId); + String value = FIRMWARE.equals(this.type) ? LwM2mTransportUtil.UpdateResultFw.fromUpdateResultFwByCode(updateResult.intValue()).type : + LwM2mTransportUtil.UpdateResultSw.fromUpdateResultSwByCode(updateResult.intValue()).type; + String key = splitCamelCaseString((String) this.lwM2MClient.getResourceName (null, this.pathResultId)); + if (success) { + this.stateUpdate = FirmwareUpdateStatus.UPDATED.name(); + this.sendLogs(EXECUTE.name(), LOG_LW2M_INFO, null); + } + else { + this.stateUpdate = FirmwareUpdateStatus.FAILED.name(); + this.sendLogs(EXECUTE.name(), LOG_LW2M_ERROR, value); + } + this.serviceImpl.helper.sendParametersOnThingsboardTelemetry( + this.serviceImpl.helper.getKvStringtoThingsboard(key, value), this.lwM2MClient.getSession()); + } + + /** + * After operation Execute success inspection Update Result : + * 2 - "Software successfully installed." + */ + public boolean conditionalSwExecuteAfterSuccess() { + Long updateResult = (Long) this.lwM2MClient.getResourceValue(null, this.pathResultId); + return LwM2mTransportUtil.UpdateResultSw.SUCCESSFULLY_INSTALLED.code == updateResult; + } + /** + * After operation Execute success inspection Update Result : + * >= 50 - error "NOT_ENOUGH_STORAGE" + */ + public boolean conditionalSwExecuteAfterError() { + Long updateResult = (Long) this.lwM2MClient.getResourceValue(null, this.pathResultId); + return LwM2mTransportUtil.UpdateResultSw.NOT_ENOUGH_STORAGE.code <= updateResult; } private void observeStateUpdate() { @@ -309,25 +337,21 @@ public class LwM2mFwSwUpdate { } } - public void sendReadInfo(DefaultLwM2MTransportMsgHandler serviceImpl) { + public void sendReadObserveInfo(DefaultLwM2MTransportMsgHandler serviceImpl) { + this.infoFwSwUpdate = true; 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(), + this.serviceImpl.lwM2mTransportRequest.sendAllRequest(this.lwM2MClient.getRegistration(), pathIdVer, OBSERVE, ContentFormat.TLV.getName(), null, 0, null); }); + } } diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/TbLwM2mSecurityStore.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/TbLwM2mSecurityStore.java index e6ed99c5e6..d71df62606 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/TbLwM2mSecurityStore.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/TbLwM2mSecurityStore.java @@ -70,7 +70,7 @@ public class TbLwM2mSecurityStore implements EditableSecurityStore { add(securityInfo); } } catch (NonUniqueSecurityInfoException e) { - log.warn("Failed to add security info: {}", securityInfo, e); + log.trace("Failed to add security info: {}", securityInfo, e); } } return securityInfo; @@ -86,7 +86,7 @@ public class TbLwM2mSecurityStore implements EditableSecurityStore { add(securityInfo); } } catch (NonUniqueSecurityInfoException e) { - log.warn("Failed to add security info: {}", securityInfo, e); + log.trace("Failed to add security info: {}", securityInfo, e); } } return securityInfo; 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 77a18af6bc..acc6ea1857 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 @@ -121,9 +121,11 @@ public class LwM2mValueConverterImpl implements LwM2mValueConverter { /** let's assume we received an ISO 8601 format date */ try { return new Date(Long.decode(value.toString())); -// DatatypeFactory datatypeFactory = DatatypeFactory.newInstance(); -// XMLGregorianCalendar cal = datatypeFactory.newXMLGregorianCalendar((String) value); -// return cal.toGregorianCalendar().getTime(); + /** + DatatypeFactory datatypeFactory = DatatypeFactory.newInstance(); + XMLGregorianCalendar cal = datatypeFactory.newXMLGregorianCalendar((String) value); + return cal.toGregorianCalendar().getTime(); + **/ } catch (IllegalArgumentException e) { log.debug("Unable to convert string to date", e); throw new CodecException("Unable to convert string (%s) to date for resource %s", value, diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/DeviceProfileEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/DeviceProfileEntity.java index 538e892601..f2124ecbab 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/DeviceProfileEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/DeviceProfileEntity.java @@ -117,7 +117,6 @@ public final class DeviceProfileEntity extends BaseSqlEntity impl this.setCreatedTime(deviceProfile.getCreatedTime()); this.name = deviceProfile.getName(); this.type = deviceProfile.getType(); - this.image = deviceProfile.getImage(); this.transportType = deviceProfile.getTransportType(); this.provisionType = deviceProfile.getProvisionType(); this.description = deviceProfile.getDescription(); @@ -126,16 +125,13 @@ public final class DeviceProfileEntity extends BaseSqlEntity impl if (deviceProfile.getDefaultRuleChainId() != null) { this.defaultRuleChainId = deviceProfile.getDefaultRuleChainId().getId(); } - if (deviceProfile.getDefaultDashboardId() != null) { - this.defaultDashboardId = deviceProfile.getDefaultDashboardId().getId(); - } this.defaultQueueName = deviceProfile.getDefaultQueueName(); this.provisionDeviceKey = deviceProfile.getProvisionDeviceKey(); if (deviceProfile.getFirmwareId() != null) { this.firmwareId = deviceProfile.getFirmwareId().getId(); } if (deviceProfile.getSoftwareId() != null) { - this.firmwareId = deviceProfile.getSoftwareId().getId(); + this.softwareId = deviceProfile.getSoftwareId().getId(); } }