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