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.Device;
|
||||||
import org.thingsboard.server.common.data.DeviceProfile;
|
import org.thingsboard.server.common.data.DeviceProfile;
|
||||||
import org.thingsboard.server.common.data.FirmwareInfo;
|
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.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.DeviceId;
|
||||||
import org.thingsboard.server.common.data.id.FirmwareId;
|
import org.thingsboard.server.common.data.id.FirmwareId;
|
||||||
import org.thingsboard.server.common.data.id.TenantId;
|
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.TITLE;
|
||||||
import static org.thingsboard.server.common.data.firmware.FirmwareKey.TS;
|
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.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.getAttributeKey;
|
||||||
import static org.thingsboard.server.common.data.firmware.FirmwareUtil.getTargetTelemetryKey;
|
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.FirmwareUtil.getTelemetryKey;
|
||||||
import static org.thingsboard.server.common.data.firmware.FirmwareType.FIRMWARE;
|
|
||||||
import static org.thingsboard.server.common.data.firmware.FirmwareType.SOFTWARE;
|
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
|
|||||||
@ -44,6 +44,7 @@ import java.util.Base64;
|
|||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
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_KEY;
|
||||||
import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_SEARCH_TEXT;
|
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,
|
List<TbResource> resources = resourceService.findTenantResourcesByResourceTypeAndObjectIds(tenantId, ResourceType.LWM2M_MODEL,
|
||||||
objectIds);
|
objectIds);
|
||||||
return resources.stream()
|
return resources.stream()
|
||||||
.map(this::toLwM2mObject)
|
.flatMap(s -> Stream.ofNullable(toLwM2mObject(s)))
|
||||||
.sorted(getComparator(sortProperty, sortOrder))
|
.sorted(getComparator(sortProperty, sortOrder))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
@ -141,7 +142,7 @@ public class DefaultTbResourceService implements TbResourceService {
|
|||||||
validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
|
validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
|
||||||
PageData<TbResource> resourcePageData = resourceService.findTenantResourcesByResourceTypeAndPageLink(tenantId, ResourceType.LWM2M_MODEL, pageLink);
|
PageData<TbResource> resourcePageData = resourceService.findTenantResourcesByResourceTypeAndPageLink(tenantId, ResourceType.LWM2M_MODEL, pageLink);
|
||||||
return resourcePageData.getData().stream()
|
return resourcePageData.getData().stream()
|
||||||
.map(this::toLwM2mObject)
|
.flatMap(s -> Stream.ofNullable(toLwM2mObject(s)))
|
||||||
.sorted(getComparator(sortProperty, sortOrder))
|
.sorted(getComparator(sortProperty, sortOrder))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
@ -190,10 +191,15 @@ public class DefaultTbResourceService implements TbResourceService {
|
|||||||
resources.add(lwM2MResourceObserve);
|
resources.add(lwM2MResourceObserve);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
if (resources.size() > 0) {
|
||||||
instance.setResources(resources.toArray(LwM2mResourceObserve[]::new));
|
instance.setResources(resources.toArray(LwM2mResourceObserve[]::new));
|
||||||
lwM2mObject.setInstances(new LwM2mInstance[]{instance});
|
lwM2mObject.setInstances(new LwM2mInstance[]{instance});
|
||||||
return lwM2mObject;
|
return lwM2mObject;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
} catch (IOException | InvalidDDFFileException e) {
|
} catch (IOException | InvalidDDFFileException e) {
|
||||||
log.error("Could not parse the XML of objectModel with name [{}]", resource.getSearchText(), e);
|
log.error("Could not parse the XML of objectModel with name [{}]", resource.getSearchText(), e);
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@ -672,6 +672,8 @@ transport:
|
|||||||
recommended_supported_groups: "${LWM2M_RECOMMENDED_SUPPORTED_GROUPS:true}"
|
recommended_supported_groups: "${LWM2M_RECOMMENDED_SUPPORTED_GROUPS:true}"
|
||||||
response_pool_size: "${LWM2M_RESPONSE_POOL_SIZE:100}"
|
response_pool_size: "${LWM2M_RESPONSE_POOL_SIZE:100}"
|
||||||
registered_pool_size: "${LWM2M_REGISTERED_POOL_SIZE:10}"
|
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}"
|
update_registered_pool_size: "${LWM2M_UPDATE_REGISTERED_POOL_SIZE:10}"
|
||||||
un_registered_pool_size: "${LWM2M_UN_REGISTERED_POOL_SIZE:10}"
|
un_registered_pool_size: "${LWM2M_UN_REGISTERED_POOL_SIZE:10}"
|
||||||
log_max_length: "${LWM2M_LOG_MAX_LENGTH:100}"
|
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.common.data.security.Authority;
|
||||||
import org.thingsboard.server.controller.AbstractControllerTest;
|
import org.thingsboard.server.controller.AbstractControllerTest;
|
||||||
import org.thingsboard.server.dao.exception.DataValidationException;
|
import org.thingsboard.server.dao.exception.DataValidationException;
|
||||||
import org.thingsboard.server.dao.service.AbstractServiceTest;
|
|
||||||
import org.thingsboard.server.dao.service.DaoSqlTest;
|
import org.thingsboard.server.dao.service.DaoSqlTest;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -57,7 +56,7 @@ public class BaseTbResourceServiceTest extends AbstractControllerTest {
|
|||||||
"<Resources>\n" +
|
"<Resources>\n" +
|
||||||
"<Item ID=\"0\">\n" +
|
"<Item ID=\"0\">\n" +
|
||||||
"<Name>LWM2M</Name>\n" +
|
"<Name>LWM2M</Name>\n" +
|
||||||
"<Operations></Operations>\n" +
|
"<Operations>RW</Operations>\n" +
|
||||||
"<MultipleInstances>Single</MultipleInstances>\n" +
|
"<MultipleInstances>Single</MultipleInstances>\n" +
|
||||||
"<Mandatory>Mandatory</Mandatory>\n" +
|
"<Mandatory>Mandatory</Mandatory>\n" +
|
||||||
"<Type>String</Type>\n" +
|
"<Type>String</Type>\n" +
|
||||||
|
|||||||
@ -92,26 +92,6 @@ public class DataConstants {
|
|||||||
public static final String CLIENT_ID = "clientId";
|
public static final String CLIENT_ID = "clientId";
|
||||||
public static final String USERNAME = "username";
|
public static final String USERNAME = "username";
|
||||||
public static final String PASSWORD = "password";
|
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 EDGE_MSG_SOURCE = "edge";
|
||||||
public static final String MSG_SOURCE_KEY = "source";
|
public static final String MSG_SOURCE_KEY = "source";
|
||||||
|
|
||||||
|
|||||||
@ -13,7 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.thingsboard.server.service.firmware;
|
package org.thingsboard.server.common.data.firmware;
|
||||||
|
|
||||||
public enum FirmwareUpdateStatus {
|
public enum FirmwareUpdateStatus {
|
||||||
QUEUED, INITIATED, DOWNLOADING, DOWNLOADED, VERIFIED, UPDATING, UPDATED, FAILED
|
QUEUED, INITIATED, DOWNLOADING, DOWNLOADED, VERIFIED, UPDATING, UPDATED, FAILED
|
||||||
@ -64,6 +64,14 @@ public class LwM2MTransportServerConfig implements LwM2MSecureServerConfig {
|
|||||||
@Value("${transport.lwm2m.registered_pool_size:}")
|
@Value("${transport.lwm2m.registered_pool_size:}")
|
||||||
private int registeredPoolSize;
|
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
|
@Getter
|
||||||
@Value("${transport.lwm2m.update_registered_pool_size:}")
|
@Value("${transport.lwm2m.update_registered_pool_size:}")
|
||||||
private int updateRegisteredPoolSize;
|
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.DeviceProfile;
|
||||||
import org.thingsboard.server.common.data.firmware.FirmwareKey;
|
import org.thingsboard.server.common.data.firmware.FirmwareKey;
|
||||||
import org.thingsboard.server.common.data.firmware.FirmwareType;
|
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.firmware.FirmwareUtil;
|
||||||
import org.thingsboard.server.common.data.id.FirmwareId;
|
import org.thingsboard.server.common.data.id.FirmwareId;
|
||||||
import org.thingsboard.server.common.transport.TransportService;
|
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.californium.core.coap.CoAP.ResponseCode.BAD_REQUEST;
|
||||||
import static org.eclipse.leshan.core.attributes.Attribute.OBJECT_VERSION;
|
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.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.LwM2mTransportServerHelper.getValueFromKvProto;
|
||||||
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.CLIENT_NOT_AUTHORIZED;
|
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.DEVICE_ATTRIBUTES_REQUEST;
|
||||||
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FR_OBJECT_ID;
|
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.EqualsFwSateToFirmwareUpdateStatus;
|
||||||
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FR_PATH_RESOURCE_VER_ID;
|
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_ERROR;
|
||||||
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_INFO;
|
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.LOG_LW2M_VALUE;
|
||||||
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LWM2M_STRATEGY_2;
|
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;
|
||||||
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.DISCOVER;
|
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.EXECUTE;
|
||||||
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.OBSERVE;
|
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.OBSERVE;
|
||||||
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.OBSERVE_CANCEL;
|
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_ATTRIBUTES;
|
||||||
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.WRITE_REPLACE;
|
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.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.convertJsonArrayToSet;
|
||||||
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertPathFromIdVerToObjectId;
|
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.convertPathFromObjectIdToIdVer;
|
||||||
@ -124,12 +128,12 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
|
|||||||
|
|
||||||
private final TransportService transportService;
|
private final TransportService transportService;
|
||||||
private final LwM2mTransportContext context;
|
private final LwM2mTransportContext context;
|
||||||
private final LwM2MTransportServerConfig config;
|
public final LwM2MTransportServerConfig config;
|
||||||
private final FirmwareDataCache firmwareDataCache;
|
public final FirmwareDataCache firmwareDataCache;
|
||||||
private final LwM2mTransportServerHelper helper;
|
public final LwM2mTransportServerHelper helper;
|
||||||
private final LwM2MJsonAdaptor adaptor;
|
private final LwM2MJsonAdaptor adaptor;
|
||||||
private final LwM2mClientContext clientContext;
|
private final LwM2mClientContext clientContext;
|
||||||
private final LwM2mTransportRequest lwM2mTransportRequest;
|
public final LwM2mTransportRequest lwM2mTransportRequest;
|
||||||
|
|
||||||
public DefaultLwM2MTransportMsgHandler(TransportService transportService, LwM2MTransportServerConfig config, LwM2mTransportServerHelper helper,
|
public DefaultLwM2MTransportMsgHandler(TransportService transportService, LwM2MTransportServerConfig config, LwM2mTransportServerHelper helper,
|
||||||
LwM2mClientContext clientContext,
|
LwM2mClientContext clientContext,
|
||||||
@ -182,6 +186,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
|
|||||||
transportService.process(sessionInfo, TransportProtos.SubscribeToAttributeUpdatesMsg.newBuilder().build(), null);
|
transportService.process(sessionInfo, TransportProtos.SubscribeToAttributeUpdatesMsg.newBuilder().build(), null);
|
||||||
transportService.process(sessionInfo, TransportProtos.SubscribeToRPCMsg.newBuilder().build(), null);
|
transportService.process(sessionInfo, TransportProtos.SubscribeToRPCMsg.newBuilder().build(), null);
|
||||||
this.getInfoFirmwareUpdate(lwM2MClient);
|
this.getInfoFirmwareUpdate(lwM2MClient);
|
||||||
|
this.getInfoSoftwareUpdate(lwM2MClient);
|
||||||
this.initLwM2mFromClientValue(registration, lwM2MClient);
|
this.initLwM2mFromClientValue(registration, lwM2MClient);
|
||||||
this.sendLogsToThingsboard(LOG_LW2M_INFO + ": Client create after Registration", registration.getId());
|
this.sendLogsToThingsboard(LOG_LW2M_INFO + ": Client create after Registration", registration.getId());
|
||||||
} else {
|
} else {
|
||||||
@ -327,9 +332,16 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
|
|||||||
String pathName = tsKvProto.getKv().getKey();
|
String pathName = tsKvProto.getKv().getKey();
|
||||||
String pathIdVer = this.getPresentPathIntoProfile(sessionInfo, pathName);
|
String pathIdVer = this.getPresentPathIntoProfile(sessionInfo, pathName);
|
||||||
Object valueNew = getValueFromKvProto(tsKvProto.getKv());
|
Object valueNew = getValueFromKvProto(tsKvProto.getKv());
|
||||||
//TODO: react on change of the firmware name.
|
if ((FirmwareUtil.getAttributeKey(FirmwareType.FIRMWARE, FirmwareKey.VERSION).equals(pathName)
|
||||||
if (FirmwareUtil.getAttributeKey(FirmwareType.FIRMWARE, FirmwareKey.VERSION).equals(pathName) && !valueNew.equals(lwM2MClient.getFrUpdate().getCurrentFwVersion())) {
|
&& (!valueNew.equals(lwM2MClient.getFwUpdate().getCurrentVersion())))
|
||||||
|
|| (FirmwareUtil.getAttributeKey(FirmwareType.FIRMWARE, FirmwareKey.TITLE).equals(pathName)
|
||||||
|
&& (!valueNew.equals(lwM2MClient.getFwUpdate().getCurrentTitle())))) {
|
||||||
this.getInfoFirmwareUpdate(lwM2MClient);
|
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) {
|
if (pathIdVer != null) {
|
||||||
ResourceModel resourceModel = lwM2MClient.getResourceModel(pathIdVer, this.config
|
ResourceModel resourceModel = lwM2MClient.getResourceModel(pathIdVer, this.config
|
||||||
@ -354,8 +366,8 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
|
|||||||
msg.getSharedUpdatedList().forEach(tsKvProto -> {
|
msg.getSharedUpdatedList().forEach(tsKvProto -> {
|
||||||
String pathName = tsKvProto.getKv().getKey();
|
String pathName = tsKvProto.getKv().getKey();
|
||||||
Object valueNew = getValueFromKvProto(tsKvProto.getKv());
|
Object valueNew = getValueFromKvProto(tsKvProto.getKv());
|
||||||
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())) {
|
||||||
lwM2MClient.getFrUpdate().setCurrentFwVersion((String) valueNew);
|
lwM2MClient.getFwUpdate().setCurrentVersion((String) valueNew);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
log.info("[{}] delete [{}] onAttributeUpdate", msg.getSharedDeletedList(), sessionInfo);
|
log.info("[{}] delete [{}] onAttributeUpdate", msg.getSharedDeletedList(), sessionInfo);
|
||||||
@ -464,18 +476,18 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
|
|||||||
if (paramsResourceId.size() > 0) {
|
if (paramsResourceId.size() > 0) {
|
||||||
lwm2mClientRpcRequest.setParams(paramsResourceId);
|
lwm2mClientRpcRequest.setParams(paramsResourceId);
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
lwm2mClientRpcRequest.setParams(params);
|
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)
|
new Gson().fromJson(rpcRequest.get(lwm2mClientRpcRequest.paramsKey)
|
||||||
.getAsJsonObject().toString(), new TypeToken<ConcurrentHashMap<String, Object>>() {
|
.getAsJsonObject().toString(), new TypeToken<ConcurrentHashMap<String, Object>>() {
|
||||||
}.getType());
|
}.getType());
|
||||||
}
|
}
|
||||||
lwm2mClientRpcRequest.setSessionInfo(sessionInfo);
|
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.setErrorMsg(lwm2mClientRpcRequest.targetIdVerKey + " and " +
|
||||||
lwm2mClientRpcRequest.keyNameKey + " is null or bad format");
|
lwm2mClientRpcRequest.keyNameKey + " is null or bad format");
|
||||||
}
|
}
|
||||||
@ -678,18 +690,31 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
|
|||||||
LwM2mClient lwM2MClient = clientContext.getOrRegister(registration);
|
LwM2mClient lwM2MClient = clientContext.getOrRegister(registration);
|
||||||
if (lwM2MClient.saveResourceValue(path, lwM2mResource, this.config
|
if (lwM2MClient.saveResourceValue(path, lwM2mResource, this.config
|
||||||
.getModelProvider())) {
|
.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
|
/** version != null
|
||||||
* set setClient_fw_version = value
|
* set setClient_fw_info... = value
|
||||||
**/
|
**/
|
||||||
lwM2MClient.setUpdateFw(false);
|
if (lwM2MClient.getFwUpdate().isInfoFwSwUpdate()) {
|
||||||
lwM2MClient.getFrUpdate().setClientFwVersion(lwM2mResource.getValue().toString());
|
lwM2MClient.getFwUpdate().initReadValue(this, path);
|
||||||
log.warn("updateFirmwareClient3");
|
}
|
||||||
this.updateFirmwareClient(lwM2MClient);
|
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<>();
|
Set<String> paths = new HashSet<>();
|
||||||
paths.add(path);
|
paths.add(path);
|
||||||
@ -845,7 +870,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
|
|||||||
Object finalvalueKvProto = valueKvProto;
|
Object finalvalueKvProto = valueKvProto;
|
||||||
Gson gson = new GsonBuilder().create();
|
Gson gson = new GsonBuilder().create();
|
||||||
resourceValue.getValues().forEach((k, v) -> {
|
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)));
|
new LwM2mPath(convertPathFromIdVerToObjectId(pathIdVer)));
|
||||||
JsonElement element = gson.toJsonTree(val, val.getClass());
|
JsonElement element = gson.toJsonTree(val, val.getClass());
|
||||||
((JsonObject) finalvalueKvProto).add(String.valueOf(k), element);
|
((JsonObject) finalvalueKvProto).add(String.valueOf(k), element);
|
||||||
@ -937,7 +962,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
|
|||||||
*/
|
*/
|
||||||
private void onDeviceProfileUpdate(Set<String> registrationIds, DeviceProfile deviceProfile) {
|
private void onDeviceProfileUpdate(Set<String> registrationIds, DeviceProfile deviceProfile) {
|
||||||
LwM2mClientProfile lwM2MClientProfileOld = clientContext.getProfiles().get(deviceProfile.getUuidId()).clone();
|
LwM2mClientProfile lwM2MClientProfileOld = clientContext.getProfiles().get(deviceProfile.getUuidId()).clone();
|
||||||
if (clientContext.toClientProfile(deviceProfile) != null) {
|
if (clientContext.profileUpdate(deviceProfile) != null) {
|
||||||
// #1
|
// #1
|
||||||
JsonArray attributeOld = lwM2MClientProfileOld.getPostAttributeProfile();
|
JsonArray attributeOld = lwM2MClientProfileOld.getPostAttributeProfile();
|
||||||
Set<String> attributeSetOld = convertJsonArrayToSet(attributeOld);
|
Set<String> attributeSetOld = convertJsonArrayToSet(attributeOld);
|
||||||
@ -947,7 +972,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
|
|||||||
JsonObject keyNameOld = lwM2MClientProfileOld.getPostKeyNameProfile();
|
JsonObject keyNameOld = lwM2MClientProfileOld.getPostKeyNameProfile();
|
||||||
JsonObject attributeLwm2mOld = lwM2MClientProfileOld.getPostAttributeLwm2mProfile();
|
JsonObject attributeLwm2mOld = lwM2MClientProfileOld.getPostAttributeLwm2mProfile();
|
||||||
|
|
||||||
LwM2mClientProfile lwM2MClientProfileNew = clientContext.getProfiles().get(deviceProfile.getUuidId());
|
LwM2mClientProfile lwM2MClientProfileNew = clientContext.getProfiles().get(deviceProfile.getUuidId()).clone();
|
||||||
JsonArray attributeNew = lwM2MClientProfileNew.getPostAttributeProfile();
|
JsonArray attributeNew = lwM2MClientProfileNew.getPostAttributeProfile();
|
||||||
Set<String> attributeSetNew = convertJsonArrayToSet(attributeNew);
|
Set<String> attributeSetNew = convertJsonArrayToSet(attributeNew);
|
||||||
JsonArray telemetryNew = lwM2MClientProfileNew.getPostTelemetryProfile();
|
JsonArray telemetryNew = lwM2MClientProfileNew.getPostTelemetryProfile();
|
||||||
@ -996,7 +1021,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
|
|||||||
Registration registration = clientContext.getRegistration(registrationId);
|
Registration registration = clientContext.getRegistration(registrationId);
|
||||||
this.readObserveFromProfile(registration, sendAttrToThingsboard.getPathPostParametersAdd(), READ);
|
this.readObserveFromProfile(registration, sendAttrToThingsboard.getPathPostParametersAdd(), READ);
|
||||||
// send attr/telemetry to tingsboard for new path
|
// send attr/telemetry to tingsboard for new path
|
||||||
this.updateAttrTelemetry(registration, sendAttrToThingsboard.getPathPostParametersAdd());
|
// this.updateAttrTelemetry(registration, sendAttrToThingsboard.getPathPostParametersAdd());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// #4.2 del
|
// #4.2 del
|
||||||
@ -1275,7 +1300,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
|
|||||||
* @param registration - Registration LwM2M Client
|
* @param registration - Registration LwM2M Client
|
||||||
* @return - sessionInfo after access connect client
|
* @return - sessionInfo after access connect client
|
||||||
*/
|
*/
|
||||||
private SessionInfoProto getSessionInfoOrCloseSession(Registration registration) {
|
public SessionInfoProto getSessionInfoOrCloseSession(Registration registration) {
|
||||||
return getSessionInfoOrCloseSession(clientContext.getOrRegister(registration));
|
return getSessionInfoOrCloseSession(clientContext.getOrRegister(registration));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1331,24 +1356,20 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void getInfoFirmwareUpdate(LwM2mClient lwM2MClient) {
|
public void getInfoFirmwareUpdate(LwM2mClient lwM2MClient) {
|
||||||
|
if (lwM2MClient.getRegistration().getSupportedVersion(FW_ID) != null) {
|
||||||
SessionInfoProto sessionInfo = this.getSessionInfoOrCloseSession(lwM2MClient);
|
SessionInfoProto sessionInfo = this.getSessionInfoOrCloseSession(lwM2MClient);
|
||||||
if (sessionInfo != null) {
|
if (sessionInfo != null) {
|
||||||
TransportProtos.GetFirmwareRequestMsg getFirmwareRequestMsg = TransportProtos.GetFirmwareRequestMsg.newBuilder()
|
DefaultLwM2MTransportMsgHandler serviceImpl = this;
|
||||||
.setDeviceIdMSB(sessionInfo.getDeviceIdMSB())
|
transportService.process(sessionInfo, createFirmwareRequestMsg(sessionInfo, FirmwareType.FIRMWARE.name()),
|
||||||
.setDeviceIdLSB(sessionInfo.getDeviceIdLSB())
|
|
||||||
.setTenantIdMSB(sessionInfo.getTenantIdMSB())
|
|
||||||
.setTenantIdLSB(sessionInfo.getTenantIdLSB())
|
|
||||||
.setType(FirmwareType.FIRMWARE.name())
|
|
||||||
.build();
|
|
||||||
transportService.process(sessionInfo, getFirmwareRequestMsg,
|
|
||||||
new TransportServiceCallback<>() {
|
new TransportServiceCallback<>() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(TransportProtos.GetFirmwareResponseMsg response) {
|
public void onSuccess(TransportProtos.GetFirmwareResponseMsg response) {
|
||||||
if (TransportProtos.ResponseStatus.SUCCESS.equals(response.getResponseStatus())) {
|
if (TransportProtos.ResponseStatus.SUCCESS.equals(response.getResponseStatus())
|
||||||
lwM2MClient.getFrUpdate().setCurrentFwVersion(response.getVersion());
|
&& response.getType().equals(FirmwareType.FIRMWARE.name())) {
|
||||||
lwM2MClient.getFrUpdate().setCurrentFwId(new FirmwareId(new UUID(response.getFirmwareIdMSB(), response.getFirmwareIdLSB())).getId());
|
lwM2MClient.getFwUpdate().setCurrentVersion(response.getVersion());
|
||||||
lwM2MClient.setUpdateFw(true);
|
lwM2MClient.getFwUpdate().setCurrentTitle(response.getTitle());
|
||||||
readRequestToClientFirmwareVer(lwM2MClient.getRegistration());
|
lwM2MClient.getFwUpdate().setCurrentId(new FirmwareId(new UUID(response.getFirmwareIdMSB(), response.getFirmwareIdLSB())).getId());
|
||||||
|
lwM2MClient.getFwUpdate().sendReadInfo(serviceImpl);
|
||||||
} else {
|
} else {
|
||||||
log.trace("Firmware [{}] [{}]", lwM2MClient.getDeviceName(), response.getResponseStatus().toString());
|
log.trace("Firmware [{}] [{}]", lwM2MClient.getDeviceName(), response.getResponseStatus().toString());
|
||||||
}
|
}
|
||||||
@ -1356,37 +1377,51 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onError(Throwable e) {
|
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public void getInfoSoftwareUpdate(LwM2mClient lwM2MClient) {
|
||||||
* @param lwM2MClient -
|
if (lwM2MClient.getRegistration().getSupportedVersion(SW_ID) != null) {
|
||||||
*/
|
SessionInfoProto sessionInfo = this.getSessionInfoOrCloseSession(lwM2MClient);
|
||||||
public void updateFirmwareClient(LwM2mClient lwM2MClient) {
|
if (sessionInfo != null) {
|
||||||
if (!lwM2MClient.getFrUpdate().getCurrentFwVersion().equals(lwM2MClient.getFrUpdate().getClientFwVersion())) {
|
DefaultLwM2MTransportMsgHandler serviceImpl = this;
|
||||||
int chunkSize = 0;
|
transportService.process(sessionInfo, createFirmwareRequestMsg(sessionInfo, FirmwareType.SOFTWARE.name()),
|
||||||
int chunk = 0;
|
new TransportServiceCallback<>() {
|
||||||
byte[] firmwareChunk = firmwareDataCache.get(lwM2MClient.getFrUpdate().getCurrentFwId().toString(), chunkSize, chunk);
|
@Override
|
||||||
String verSupportedObject = lwM2MClient.getRegistration().getSupportedObject().get(FR_OBJECT_ID);
|
public void onSuccess(TransportProtos.GetFirmwareResponseMsg response) {
|
||||||
String targetIdVer = LWM2M_SEPARATOR_PATH + FR_OBJECT_ID + LWM2M_SEPARATOR_KEY + verSupportedObject + LWM2M_SEPARATOR_PATH + 0 + LWM2M_SEPARATOR_PATH + 0;
|
if (TransportProtos.ResponseStatus.SUCCESS.equals(response.getResponseStatus())
|
||||||
lwM2mTransportRequest.sendAllRequest(lwM2MClient.getRegistration(), targetIdVer, WRITE_REPLACE, ContentFormat.OPAQUE.getName(),
|
&& response.getType().equals(FirmwareType.SOFTWARE.name())) {
|
||||||
firmwareChunk, config.getTimeout(), null);
|
lwM2MClient.getSwUpdate().setCurrentVersion(response.getVersion());
|
||||||
log.warn("updateFirmwareClient [{}] [{}]", lwM2MClient.getFrUpdate().getCurrentFwVersion(), lwM2MClient.getFrUpdate().getClientFwVersion());
|
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 !!!
|
* !!! 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.LeshanServer;
|
||||||
import org.eclipse.leshan.server.californium.LeshanServerBuilder;
|
import org.eclipse.leshan.server.californium.LeshanServerBuilder;
|
||||||
import org.eclipse.leshan.server.californium.registration.CaliforniumRegistrationStore;
|
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.model.LwM2mModelProvider;
|
||||||
import org.eclipse.leshan.server.security.DefaultAuthorizer;
|
import org.eclipse.leshan.server.security.DefaultAuthorizer;
|
||||||
import org.eclipse.leshan.server.security.EditableSecurityStore;
|
import org.eclipse.leshan.server.security.EditableSecurityStore;
|
||||||
import org.eclipse.leshan.server.security.SecurityChecker;
|
import org.eclipse.leshan.server.security.SecurityChecker;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.thingsboard.common.util.ThingsBoardThreadFactory;
|
||||||
import org.thingsboard.server.common.data.StringUtils;
|
import org.thingsboard.server.common.data.StringUtils;
|
||||||
import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;
|
import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;
|
||||||
import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig;
|
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.KeySpec;
|
||||||
import java.security.spec.PKCS8EncodedKeySpec;
|
import java.security.spec.PKCS8EncodedKeySpec;
|
||||||
import java.util.Arrays;
|
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_CBC_SHA256;
|
||||||
import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8;
|
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 CaliforniumRegistrationStore registrationStore;
|
||||||
private final EditableSecurityStore securityStore;
|
private final EditableSecurityStore securityStore;
|
||||||
private final LwM2mClientContext lwM2mClientContext;
|
private final LwM2mClientContext lwM2mClientContext;
|
||||||
|
private ScheduledExecutorService registrationStoreExecutor;
|
||||||
|
|
||||||
private LeshanServer server;
|
private LeshanServer server;
|
||||||
|
|
||||||
@ -112,6 +117,9 @@ public class DefaultLwM2mTransportService implements LwM2MTransportService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private LeshanServer getLhServer() {
|
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();
|
LeshanServerBuilder builder = new LeshanServerBuilder();
|
||||||
builder.setLocalAddress(config.getHost(), config.getPort());
|
builder.setLocalAddress(config.getHost(), config.getPort());
|
||||||
builder.setLocalSecureAddress(config.getSecureHost(), config.getSecurePort());
|
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. */
|
/* Use a magic converter to support bad type send by the UI. */
|
||||||
builder.setEncoder(new DefaultLwM2mNodeEncoder(LwM2mValueConverterImpl.getInstance()));
|
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 */
|
/* Create CoAP Config */
|
||||||
builder.setCoapConfig(getCoapConfig(config.getPort(), config.getSecurePort()));
|
builder.setCoapConfig(getCoapConfig(config.getPort(), config.getSecurePort()));
|
||||||
|
|||||||
@ -88,7 +88,7 @@ public class LwM2mServerListener {
|
|||||||
public void cancelled(Observation observation) {
|
public void cancelled(Observation observation) {
|
||||||
String msg = String.format("%s: Cancel Observation %s.", LOG_LW2M_INFO, observation.getPath());
|
String msg = String.format("%s: Cancel Observation %s.", LOG_LW2M_INFO, observation.getPath());
|
||||||
service.sendLogsToThingsboard(msg, observation.getRegistrationId());
|
service.sendLogsToThingsboard(msg, observation.getRegistrationId());
|
||||||
log.trace(msg);
|
log.warn(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -19,6 +19,7 @@ import lombok.RequiredArgsConstructor;
|
|||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.eclipse.californium.core.coap.CoAP;
|
import org.eclipse.californium.core.coap.CoAP;
|
||||||
import org.eclipse.californium.core.coap.Response;
|
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.model.ResourceModel;
|
||||||
import org.eclipse.leshan.core.node.LwM2mNode;
|
import org.eclipse.leshan.core.node.LwM2mNode;
|
||||||
import org.eclipse.leshan.core.node.LwM2mPath;
|
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.core.util.NamedThreadFactory;
|
||||||
import org.eclipse.leshan.server.registration.Registration;
|
import org.eclipse.leshan.server.registration.Registration;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.thingsboard.server.common.data.firmware.FirmwareUpdateStatus;
|
||||||
import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;
|
import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;
|
||||||
import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig;
|
import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig;
|
||||||
import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
|
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.BAD_REQUEST;
|
||||||
import static org.eclipse.leshan.core.ResponseCode.NOT_FOUND;
|
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.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_ERROR;
|
||||||
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_INFO;
|
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.LOG_LW2M_VALUE;
|
||||||
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper;
|
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_CANCEL;
|
||||||
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.OBSERVE_READ_ALL;
|
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.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.convertPathFromIdVerToObjectId;
|
||||||
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertPathFromObjectIdToIdVer;
|
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertPathFromObjectIdToIdVer;
|
||||||
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.createWriteAttributeRequest;
|
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.createWriteAttributeRequest;
|
||||||
@ -132,7 +136,13 @@ public class LwM2mTransportRequest {
|
|||||||
break;
|
break;
|
||||||
case OBSERVE:
|
case OBSERVE:
|
||||||
if (resultIds.isResource()) {
|
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());
|
request = new ObserveRequest(contentFormat, resultIds.getObjectId(), resultIds.getObjectInstanceId(), resultIds.getResourceId());
|
||||||
|
} else {
|
||||||
|
request = new ReadRequest(contentFormat, target);
|
||||||
|
}
|
||||||
} else if (resultIds.isObjectInstance()) {
|
} else if (resultIds.isObjectInstance()) {
|
||||||
request = new ObserveRequest(contentFormat, resultIds.getObjectId(), resultIds.getObjectInstanceId());
|
request = new ObserveRequest(contentFormat, resultIds.getObjectId(), resultIds.getObjectInstanceId());
|
||||||
} else if (resultIds.getObjectId() >= 0) {
|
} else if (resultIds.getObjectId() >= 0) {
|
||||||
@ -200,8 +210,7 @@ public class LwM2mTransportRequest {
|
|||||||
if (resources.size() > 0) {
|
if (resources.size() > 0) {
|
||||||
request = new WriteRequest(WriteRequest.Mode.UPDATE, contentFormat, resultIds.getObjectId(),
|
request = new WriteRequest(WriteRequest.Mode.UPDATE, contentFormat, resultIds.getObjectId(),
|
||||||
resultIds.getObjectInstanceId(), resources);
|
resultIds.getObjectInstanceId(), resources);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
Lwm2mClientRpcRequest rpcRequestClone = (Lwm2mClientRpcRequest) rpcRequest.clone();
|
Lwm2mClientRpcRequest rpcRequestClone = (Lwm2mClientRpcRequest) rpcRequest.clone();
|
||||||
if (rpcRequestClone != null) {
|
if (rpcRequestClone != null) {
|
||||||
String errorMsg = String.format("Path %s params is not valid", targetIdVer);
|
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);
|
String errorMsg = String.format("Path %s not found in object version", targetIdVer);
|
||||||
serviceImpl.sentRpcRequest(rpcRequest, NOT_FOUND.getName(), errorMsg, LOG_LW2M_ERROR);
|
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<Observation> observations = context.getServer().getObservationService().getObservations(registration);
|
||||||
Set<String> observationPaths = observations.stream().map(observation -> observation.getPath().toString()).collect(Collectors.toUnmodifiableSet());
|
paths = observations.stream().map(observation -> observation.getPath().toString()).collect(Collectors.toUnmodifiableSet());
|
||||||
String msg = String.format("%s: type operation %s observation paths - %s", LOG_LW2M_INFO,
|
} else {
|
||||||
OBSERVE_READ_ALL.type, observationPaths);
|
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());
|
serviceImpl.sendLogsToThingsboard(msg, registration.getId());
|
||||||
log.trace("[{}] [{}], [{}]", typeOper.name(), registration.getEndpoint(), msg);
|
log.warn("[{}] [{}], [{}]", typeOper.name(), registration.getEndpoint(), msg);
|
||||||
if (rpcRequest != null) {
|
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);
|
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,
|
private void sendRequest(Registration registration, LwM2mClient lwM2MClient, DownlinkRequest request,
|
||||||
long timeoutInMs, Lwm2mClientRpcRequest rpcRequest) {
|
long timeoutInMs, Lwm2mClientRpcRequest rpcRequest) {
|
||||||
context.getServer().send(registration, request, timeoutInMs, (ResponseCallback<?>) response -> {
|
context.getServer().send(registration, request, timeoutInMs, (ResponseCallback<?>) response -> {
|
||||||
|
|
||||||
if (!lwM2MClient.isInit()) {
|
if (!lwM2MClient.isInit()) {
|
||||||
lwM2MClient.initReadValue(this.serviceImpl, convertPathFromObjectIdToIdVer(request.getPath().toString(), registration));
|
lwM2MClient.initReadValue(this.serviceImpl, convertPathFromObjectIdToIdVer(request.getPath().toString(), registration));
|
||||||
}
|
}
|
||||||
@ -301,25 +317,21 @@ public class LwM2mTransportRequest {
|
|||||||
if (rpcRequest != null) {
|
if (rpcRequest != null) {
|
||||||
serviceImpl.sentRpcRequest(rpcRequest, response.getCode().getName(), response.getErrorMessage(), LOG_LW2M_ERROR);
|
serviceImpl.sentRpcRequest(rpcRequest, response.getCode().getName(), response.getErrorMessage(), LOG_LW2M_ERROR);
|
||||||
}
|
}
|
||||||
/* Not Found
|
/** Not Found
|
||||||
set setClient_fw_version = empty
|
set setClient_fw_info... = empty
|
||||||
*/
|
**/
|
||||||
if (FR_PATH_RESOURCE_VER_ID.equals(request.getPath().toString()) && lwM2MClient.isUpdateFw()) {
|
if (lwM2MClient.getFwUpdate().isInfoFwSwUpdate()) {
|
||||||
lwM2MClient.setUpdateFw(false);
|
lwM2MClient.getFwUpdate().initReadValue(serviceImpl, request.getPath().toString());
|
||||||
lwM2MClient.getFrUpdate().setClientFwVersion("");
|
|
||||||
log.warn("updateFirmwareClient1");
|
log.warn("updateFirmwareClient1");
|
||||||
serviceImpl.updateFirmwareClient(lwM2MClient);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, e -> {
|
}, e -> {
|
||||||
/* version == null
|
/** version == null
|
||||||
set setClient_fw_version = empty
|
set setClient_fw_info... = empty
|
||||||
*/
|
**/
|
||||||
if (FR_PATH_RESOURCE_VER_ID.equals(request.getPath().toString()) && lwM2MClient.isUpdateFw()) {
|
if (lwM2MClient.getFwUpdate().isInfoFwSwUpdate()) {
|
||||||
lwM2MClient.setUpdateFw(false);
|
lwM2MClient.getFwUpdate().initReadValue(serviceImpl, request.getPath().toString());
|
||||||
lwM2MClient.getFrUpdate().setClientFwVersion("");
|
|
||||||
log.warn("updateFirmwareClient2");
|
log.warn("updateFirmwareClient2");
|
||||||
serviceImpl.updateFirmwareClient(lwM2MClient);
|
|
||||||
}
|
}
|
||||||
if (!lwM2MClient.isInit()) {
|
if (!lwM2MClient.isInit()) {
|
||||||
lwM2MClient.initReadValue(this.serviceImpl, convertPathFromObjectIdToIdVer(request.getPath().toString(), registration));
|
lwM2MClient.initReadValue(this.serviceImpl, convertPathFromObjectIdToIdVer(request.getPath().toString(), registration));
|
||||||
@ -458,21 +470,35 @@ public class LwM2mTransportRequest {
|
|||||||
Math.min(valueLength, config.getLogMaxLength())));
|
Math.min(valueLength, config.getLogMaxLength())));
|
||||||
}
|
}
|
||||||
value = valueLength > config.getLogMaxLength() ? value + "..." : value;
|
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);
|
LOG_LW2M_INFO, response.getCode().getCode(), request.getPath().toString(), valueLength, value);
|
||||||
} else {
|
} else {
|
||||||
value = this.converter.convertValue(singleResource.getValue(),
|
value = this.converter.convertValue(singleResource.getValue(),
|
||||||
singleResource.getType(), ResourceModel.Type.STRING, request.getPath());
|
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);
|
LOG_LW2M_INFO, response.getCode().getCode(), request.getPath().toString(), value);
|
||||||
}
|
}
|
||||||
if (msg != null) {
|
if (msg != null) {
|
||||||
serviceImpl.sendLogsToThingsboard(msg, registration.getId());
|
serviceImpl.sendLogsToThingsboard(msg, registration.getId());
|
||||||
log.warn("[{}] [{}] [{}] - [{}] [{}] Update finished successfully: [{}]", request.getClass().getName(), registration.getEndpoint(),
|
log.warn(msg);
|
||||||
((Response) response.getCoapResponse()).getCode(), response.getCode(), request.getPath().toString(), value);
|
if (request.getPath().toString().equals(FW_PACKAGE_ID) || request.getPath().toString().equals(SW_PACKAGE_ID)) {
|
||||||
|
this.executeFwSwUpdate(registration, request);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.trace("Fail convert value from request to string. ", 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.nustaq.serialization.FSTConfiguration;
|
||||||
import org.thingsboard.server.common.data.DeviceProfile;
|
import org.thingsboard.server.common.data.DeviceProfile;
|
||||||
import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTransportConfiguration;
|
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.data.id.TenantId;
|
||||||
import org.thingsboard.server.common.transport.TransportServiceCallback;
|
import org.thingsboard.server.common.transport.TransportServiceCallback;
|
||||||
import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
|
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.OPAQUE;
|
||||||
import static org.eclipse.leshan.core.model.ResourceModel.Type.STRING;
|
import static org.eclipse.leshan.core.model.ResourceModel.Type.STRING;
|
||||||
import static org.eclipse.leshan.core.model.ResourceModel.Type.TIME;
|
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_KEY;
|
||||||
import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_PATH;
|
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 int LWM2M_STRATEGY_2 = 2;
|
||||||
|
|
||||||
public static final String CLIENT_NOT_AUTHORIZED = "Client not authorized";
|
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;
|
// FirmWare
|
||||||
public static final Integer FR_RESOURCE_VER_ID = 7;
|
public static final String FW_UPDATE = "Firmware update";
|
||||||
public static final String FR_PATH_RESOURCE_VER_ID = LWM2M_SEPARATOR_PATH + FR_OBJECT_ID + LWM2M_SEPARATOR_PATH
|
public static final Integer FW_ID = 5;
|
||||||
+ "0" + LWM2M_SEPARATOR_PATH + FR_RESOURCE_VER_ID;
|
// 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 {
|
public enum LwM2mTypeServer {
|
||||||
BOOTSTRAP(0, "bootstrap"),
|
BOOTSTRAP(0, "bootstrap"),
|
||||||
@ -144,19 +181,20 @@ public class LwM2mTransportUtil {
|
|||||||
*/
|
*/
|
||||||
READ(0, "Read"),
|
READ(0, "Read"),
|
||||||
DISCOVER(1, "Discover"),
|
DISCOVER(1, "Discover"),
|
||||||
OBSERVE_READ_ALL(2, "ObserveReadAll"),
|
DISCOVER_All(2, "DiscoverAll"),
|
||||||
|
OBSERVE_READ_ALL(3, "ObserveReadAll"),
|
||||||
/**
|
/**
|
||||||
* POST
|
* POST
|
||||||
*/
|
*/
|
||||||
OBSERVE(3, "Observe"),
|
OBSERVE(4, "Observe"),
|
||||||
OBSERVE_CANCEL(4, "ObserveCancel"),
|
OBSERVE_CANCEL(5, "ObserveCancel"),
|
||||||
EXECUTE(5, "Execute"),
|
EXECUTE(6, "Execute"),
|
||||||
/**
|
/**
|
||||||
* Replaces the Object Instance or the Resource(s) with the new value provided in the “Write” operation. (see
|
* 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).
|
* section 5.3.3 of the LW M2M spec).
|
||||||
* if all resources are to be replaced
|
* if all resources are to be replaced
|
||||||
*/
|
*/
|
||||||
WRITE_REPLACE(6, "WriteReplace"),
|
WRITE_REPLACE(7, "WriteReplace"),
|
||||||
/*
|
/*
|
||||||
PUT
|
PUT
|
||||||
*/
|
*/
|
||||||
@ -165,11 +203,13 @@ public class LwM2mTransportUtil {
|
|||||||
* 5.3.3 of the LW M2M spec).
|
* 5.3.3 of the LW M2M spec).
|
||||||
* if this is a partial update request
|
* if this is a partial update request
|
||||||
*/
|
*/
|
||||||
WRITE_UPDATE(7, "WriteUpdate"),
|
WRITE_UPDATE(8, "WriteUpdate"),
|
||||||
WRITE_ATTRIBUTES(8, "WriteAttributes"),
|
WRITE_ATTRIBUTES(9, "WriteAttributes"),
|
||||||
DELETE(9, "Delete");
|
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 int code;
|
||||||
public String type;
|
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 EVENT_AWAKE = "AWAKE";
|
||||||
public static final String RESPONSE_CHANNEL = "RESP";
|
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) {
|
switch (type) {
|
||||||
case BOOLEAN:
|
case BOOLEAN:
|
||||||
case INTEGER:
|
case INTEGER:
|
||||||
@ -256,7 +574,7 @@ public class LwM2mTransportUtil {
|
|||||||
* "/3_1.0/0/9": {"pmax": 45}, "/3_1.2": {ver": "3_1.2"}}
|
* "/3_1.0/0/9": {"pmax": 45}, "/3_1.2": {ver": "3_1.2"}}
|
||||||
*/
|
*/
|
||||||
public static LwM2mClientProfile toLwM2MClientProfile(DeviceProfile deviceProfile) {
|
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();
|
Object profile = ((Lwm2mDeviceProfileTransportConfiguration) deviceProfile.getProfileData().getTransportConfiguration()).getProperties();
|
||||||
try {
|
try {
|
||||||
ObjectMapper mapper = new ObjectMapper();
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
@ -375,7 +693,8 @@ public class LwM2mTransportUtil {
|
|||||||
return StringUtils.join(linkedListOut, "");
|
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>() {
|
return new TransportServiceCallback<Void>() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(Void dummy) {
|
public void onSuccess(Void dummy) {
|
||||||
@ -420,7 +739,8 @@ public class LwM2mTransportUtil {
|
|||||||
return null;
|
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)) {
|
if (!pathIdVer.contains(LWM2M_SEPARATOR_PATH)) {
|
||||||
throw new IllegalArgumentException(String.format("Error:"));
|
throw new IllegalArgumentException(String.format("Error:"));
|
||||||
} else {
|
} else {
|
||||||
@ -436,6 +756,7 @@ public class LwM2mTransportUtil {
|
|||||||
|
|
||||||
public static String convertPathFromObjectIdToIdVer(String path, Registration registration) {
|
public static String convertPathFromObjectIdToIdVer(String path, Registration registration) {
|
||||||
String ver = registration.getSupportedObject().get(new LwM2mPath(path).getObjectId());
|
String ver = registration.getSupportedObject().get(new LwM2mPath(path).getObjectId());
|
||||||
|
ver = ver != null ? ver : LWM2M_VERSION_DEFAULT;
|
||||||
try {
|
try {
|
||||||
String[] keyArray = path.split(LWM2M_SEPARATOR_PATH);
|
String[] keyArray = path.split(LWM2M_SEPARATOR_PATH);
|
||||||
if (keyArray.length > 1) {
|
if (keyArray.length > 1) {
|
||||||
|
|||||||
@ -27,6 +27,7 @@ import org.eclipse.leshan.server.registration.Registration;
|
|||||||
import org.eclipse.leshan.server.security.SecurityInfo;
|
import org.eclipse.leshan.server.security.SecurityInfo;
|
||||||
import org.thingsboard.server.common.data.Device;
|
import org.thingsboard.server.common.data.Device;
|
||||||
import org.thingsboard.server.common.data.DeviceProfile;
|
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.SessionInfoProto;
|
||||||
import org.thingsboard.server.gen.transport.TransportProtos.TsKvProto;
|
import org.thingsboard.server.gen.transport.TransportProtos.TsKvProto;
|
||||||
import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceCredentialsResponseMsg;
|
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.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.TRANSPORT_DEFAULT_LWM2M_VERSION;
|
||||||
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertPathFromIdVerToObjectId;
|
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.equalsResourceTypeGetSimpleName;
|
||||||
|
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.getVerFromPathIdVerOrId;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class LwM2mClient implements Cloneable {
|
public class LwM2mClient implements Cloneable {
|
||||||
@ -74,25 +76,25 @@ public class LwM2mClient implements Cloneable {
|
|||||||
private UUID profileId;
|
private UUID profileId;
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
private volatile LwM2mFirmwareUpdate frUpdate;
|
private volatile LwM2mFwSwUpdate fwUpdate;
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private volatile LwM2mFwSwUpdate swUpdate;
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
private Registration registration;
|
private Registration registration;
|
||||||
|
|
||||||
private ValidateDeviceCredentialsResponseMsg credentialsResponse;
|
private ValidateDeviceCredentialsResponseMsg credentialsResponse;
|
||||||
@Getter
|
@Getter
|
||||||
private final Map<String, ResourceValue> resources;
|
private final Map<String, ResourceValue> resources;
|
||||||
@Getter
|
@Getter
|
||||||
private final Map<String, TsKvProto> delayedRequests;
|
private final Map<String, TsKvProto> delayedRequests;
|
||||||
@Getter
|
@Getter
|
||||||
|
@Setter
|
||||||
private final List<String> pendingReadRequests;
|
private final List<String> pendingReadRequests;
|
||||||
@Getter
|
@Getter
|
||||||
private final Queue<LwM2mQueuedRequest> queuedRequests;
|
private final Queue<LwM2mQueuedRequest> queuedRequests;
|
||||||
@Getter
|
@Getter
|
||||||
private boolean init;
|
private boolean init;
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
private volatile boolean updateFw;
|
|
||||||
|
|
||||||
public Object clone() throws CloneNotSupportedException {
|
public Object clone() throws CloneNotSupportedException {
|
||||||
return super.clone();
|
return super.clone();
|
||||||
@ -109,9 +111,9 @@ public class LwM2mClient implements Cloneable {
|
|||||||
this.profileId = profileId;
|
this.profileId = profileId;
|
||||||
this.sessionId = sessionId;
|
this.sessionId = sessionId;
|
||||||
this.init = false;
|
this.init = false;
|
||||||
this.updateFw = false;
|
|
||||||
this.queuedRequests = new ConcurrentLinkedQueue<>();
|
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()) {
|
if (this.credentialsResponse != null && this.credentialsResponse.hasDeviceInfo()) {
|
||||||
this.session = createSession(nodeId, sessionId, credentialsResponse);
|
this.session = createSession(nodeId, sessionId, credentialsResponse);
|
||||||
this.deviceId = new UUID(session.getDeviceIdMSB(), session.getDeviceIdLSB());
|
this.deviceId = new UUID(session.getDeviceIdMSB(), session.getDeviceIdLSB());
|
||||||
@ -164,15 +166,15 @@ public class LwM2mClient implements Cloneable {
|
|||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean saveResourceValue(String pathRez, LwM2mResource rez, LwM2mModelProvider modelProvider) {
|
public boolean saveResourceValue(String pathRezIdVer, LwM2mResource rez, LwM2mModelProvider modelProvider) {
|
||||||
if (this.resources.get(pathRez) != null && this.resources.get(pathRez).getResourceModel() != null) {
|
if (this.resources.get(pathRezIdVer) != null && this.resources.get(pathRezIdVer).getResourceModel() != null) {
|
||||||
this.resources.get(pathRez).setLwM2mResource(rez);
|
this.resources.get(pathRezIdVer).setLwM2mResource(rez);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(pathRez));
|
LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(pathRezIdVer));
|
||||||
ResourceModel resourceModel = modelProvider.getObjectModel(registration).getResourceModel(pathIds.getObjectId(), pathIds.getResourceId());
|
ResourceModel resourceModel = modelProvider.getObjectModel(registration).getResourceModel(pathIds.getObjectId(), pathIds.getResourceId());
|
||||||
if (resourceModel != null) {
|
if (resourceModel != null) {
|
||||||
this.resources.put(pathRez, new ResourceValue(rez, resourceModel));
|
this.resources.put(pathRezIdVer, new ResourceValue(rez, resourceModel));
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
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) {
|
public ResourceModel getResourceModel(String pathIdVer, LwM2mModelProvider modelProvider) {
|
||||||
LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(pathIdVer));
|
LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(pathIdVer));
|
||||||
String verSupportedObject = registration.getSupportedObject().get(pathIds.getObjectId());
|
String verSupportedObject = registration.getSupportedObject().get(pathIds.getObjectId());
|
||||||
|
|||||||
@ -54,7 +54,7 @@ public interface LwM2mClientContext {
|
|||||||
|
|
||||||
Map<UUID, LwM2mClientProfile> setProfiles(Map<UUID, LwM2mClientProfile> profiles);
|
Map<UUID, LwM2mClientProfile> setProfiles(Map<UUID, LwM2mClientProfile> profiles);
|
||||||
|
|
||||||
LwM2mClientProfile toClientProfile(DeviceProfile deviceProfile);
|
LwM2mClientProfile profileUpdate(DeviceProfile deviceProfile);
|
||||||
|
|
||||||
Set<String> getSupportedIdVerInClient(Registration registration);
|
Set<String> getSupportedIdVerInClient(Registration registration);
|
||||||
|
|
||||||
|
|||||||
@ -16,6 +16,7 @@
|
|||||||
package org.thingsboard.server.transport.lwm2m.server.client;
|
package org.thingsboard.server.transport.lwm2m.server.client;
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.eclipse.leshan.core.node.LwM2mPath;
|
import org.eclipse.leshan.core.node.LwM2mPath;
|
||||||
import org.eclipse.leshan.server.registration.Registration;
|
import org.eclipse.leshan.server.registration.Registration;
|
||||||
import org.eclipse.leshan.server.security.EditableSecurityStore;
|
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.secure.LwM2MSecurityMode.NO_SEC;
|
||||||
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertPathFromObjectIdToIdVer;
|
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertPathFromObjectIdToIdVer;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
@TbLwM2mTransportComponent
|
@TbLwM2mTransportComponent
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@ -112,8 +114,12 @@ public class LwM2mClientContextImpl implements LwM2mClientContext {
|
|||||||
EndpointSecurityInfo securityInfo = lwM2MCredentialsSecurityInfoValidator.getEndpointSecurityInfo(endpoint, LwM2mTransportUtil.LwM2mTypeServer.CLIENT);
|
EndpointSecurityInfo securityInfo = lwM2MCredentialsSecurityInfoValidator.getEndpointSecurityInfo(endpoint, LwM2mTransportUtil.LwM2mTypeServer.CLIENT);
|
||||||
if (securityInfo.getSecurityMode() < LwM2MSecurityMode.DEFAULT_MODE.code) {
|
if (securityInfo.getSecurityMode() < LwM2MSecurityMode.DEFAULT_MODE.code) {
|
||||||
if (securityInfo.getDeviceProfile() != null) {
|
if (securityInfo.getDeviceProfile() != null) {
|
||||||
toClientProfile(securityInfo.getDeviceProfile());
|
UUID profileUuid = profileUpdate(securityInfo.getDeviceProfile())!= null ?
|
||||||
UUID profileUuid = securityInfo.getDeviceProfile().getUuidId();
|
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;
|
LwM2mClient client;
|
||||||
if (securityInfo.getSecurityInfo() != null) {
|
if (securityInfo.getSecurityInfo() != null) {
|
||||||
client = new LwM2mClient(context.getNodeId(), securityInfo.getSecurityInfo().getEndpoint(),
|
client = new LwM2mClient(context.getNodeId(), securityInfo.getSecurityInfo().getEndpoint(),
|
||||||
@ -162,14 +168,17 @@ public class LwM2mClientContextImpl implements LwM2mClientContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LwM2mClientProfile toClientProfile(DeviceProfile deviceProfile) {
|
public LwM2mClientProfile profileUpdate(DeviceProfile deviceProfile) {
|
||||||
LwM2mClientProfile lwM2MClientProfile = profiles.get(deviceProfile.getUuidId());
|
LwM2mClientProfile lwM2MClientProfile = deviceProfile != null ?
|
||||||
if (lwM2MClientProfile == null) {
|
LwM2mTransportUtil.toLwM2MClientProfile(deviceProfile) : null;
|
||||||
lwM2MClientProfile = LwM2mTransportUtil.toLwM2MClientProfile(deviceProfile);
|
if (lwM2MClientProfile != null) {
|
||||||
profiles.put(deviceProfile.getUuidId(), lwM2MClientProfile);
|
profiles.put(deviceProfile.getUuidId(), lwM2MClientProfile);
|
||||||
}
|
|
||||||
return lwM2MClientProfile;
|
return lwM2MClientProfile;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* if isVer - ok or default ver=DEFAULT_LWM2M_VERSION
|
* 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 com.google.gson.JsonObject;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.eclipse.leshan.core.request.ContentFormat;
|
import org.eclipse.leshan.core.request.ContentFormat;
|
||||||
import org.eclipse.leshan.server.registration.Registration;
|
import org.eclipse.leshan.server.registration.Registration;
|
||||||
import org.thingsboard.server.gen.transport.TransportProtos;
|
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;
|
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.validPathIdVer;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
@Data
|
@Data
|
||||||
public class Lwm2mClientRpcRequest {
|
public class Lwm2mClientRpcRequest {
|
||||||
public final String targetIdVerKey = "targetIdVer";
|
public final String targetIdVerKey = "targetIdVer";
|
||||||
@ -113,7 +115,7 @@ public class Lwm2mClientRpcRequest {
|
|||||||
try {
|
try {
|
||||||
return super.clone();
|
return super.clone();
|
||||||
} catch (CloneNotSupportedException e) {
|
} catch (CloneNotSupportedException e) {
|
||||||
e.printStackTrace();
|
log.error("", e);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user