Browse Source

LWM2M: front add Firmware/Software update strategy

pull/4680/head
nickAS21 5 years ago
parent
commit
36c7008104
  1. 6
      application/src/main/data/json/system/widget_bundles/control_widgets.json
  2. 4
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/AbstractLwm2mTransportResource.java
  3. 14
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2MTransportMsgHandler.java
  4. 4
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportCoapResource.java
  5. 10
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportRequest.java
  6. 5
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClient.java
  7. 2
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientContextImpl.java
  8. 6
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mFwSwUpdate.java
  9. 58
      ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-profile-transport-configuration.component.html
  10. 15
      ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-profile-transport-configuration.component.ts
  11. 8
      ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-profile-config.models.ts
  12. 12
      ui-ngx/src/assets/locale/locale.constant-en_US.json

6
application/src/main/data/json/system/widget_bundles/control_widgets.json

File diff suppressed because one or more lines are too long

4
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/AbstractLwm2mTransportResource.java

@ -24,11 +24,9 @@ import org.thingsboard.server.common.transport.TransportServiceCallback;
@Slf4j
public abstract class AbstractLwm2mTransportResource extends LwM2mCoapResource {
protected final LwM2mTransportMsgHandler handler;
public AbstractLwm2mTransportResource(LwM2mTransportMsgHandler handler, String name) {
public AbstractLwm2mTransportResource(String name) {
super(name);
this.handler = handler;
}
@Override

14
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2MTransportMsgHandler.java

@ -61,6 +61,7 @@ import org.thingsboard.server.transport.lwm2m.server.adaptors.LwM2MJsonAdaptor;
import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext;
import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientProfile;
import org.thingsboard.server.transport.lwm2m.server.client.LwM2mFwSwUpdate;
import org.thingsboard.server.transport.lwm2m.server.client.Lwm2mClientRpcRequest;
import org.thingsboard.server.transport.lwm2m.server.client.ResourceValue;
import org.thingsboard.server.transport.lwm2m.server.client.ResultsAddKeyValueProto;
@ -201,7 +202,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
.setSessionType(TransportProtos.SessionType.ASYNC).build())
.build(), null);
this.getInfoFirmwareUpdate(lwM2MClient, null);
// this.getInfoSoftwareUpdate(lwM2MClient, null);
this.getInfoSoftwareUpdate(lwM2MClient, null);
this.initLwM2mFromClientValue(registration, lwM2MClient);
this.sendLogsToThingsboard(LOG_LW2M_INFO + ": Client create after Registration", registration.getId());
} else {
@ -660,10 +661,10 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
/** version != null
* set setClient_fw_info... = value
**/
if (lwM2MClient.getFwUpdate().isInfoFwSwUpdate()) {
if (lwM2MClient.getFwUpdate() != null && lwM2MClient.getFwUpdate().isInfoFwSwUpdate()) {
lwM2MClient.getFwUpdate().initReadValue(this, this.lwM2mTransportRequest, path);
}
if (lwM2MClient.getSwUpdate().isInfoFwSwUpdate()) {
if (lwM2MClient.getSwUpdate() != null && lwM2MClient.getSwUpdate().isInfoFwSwUpdate()) {
lwM2MClient.getSwUpdate().initReadValue(this, this.lwM2mTransportRequest, path);
}
@ -1376,11 +1377,15 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
if (TransportProtos.ResponseStatus.SUCCESS.equals(response.getResponseStatus())
&& response.getType().equals(OtaPackageType.FIRMWARE.name())) {
log.warn("7) firmware start with ver: [{}]", response.getVersion());
lwM2MClient.setFwUpdate(new LwM2mFwSwUpdate(lwM2MClient, OtaPackageType.FIRMWARE));
// clientContext.getProfile(lwM2MClient.getProfileId()).getPostAttributeLwm2mProfile();
lwM2MClient.getFwUpdate().setTypeUpdateByURL(true);
lwM2MClient.getFwUpdate().setRpcRequest(rpcRequest);
lwM2MClient.getFwUpdate().setCurrentVersion(response.getVersion());
lwM2MClient.getFwUpdate().setCurrentTitle(response.getTitle());
log.warn("11) OtaPackageIdMSB: [{}] OtaPackageIdLSB: [{}]", response.getOtaPackageIdMSB(), response.getOtaPackageIdLSB());
lwM2MClient.getFwUpdate().setCurrentId(new UUID(response.getOtaPackageIdMSB(), response.getOtaPackageIdLSB()));
if (rpcRequest == null) {
lwM2MClient.getFwUpdate().sendReadObserveInfo(lwM2mTransportRequest);
} else {
@ -1411,6 +1416,9 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
public void onSuccess(TransportProtos.GetOtaPackageResponseMsg response) {
if (TransportProtos.ResponseStatus.SUCCESS.equals(response.getResponseStatus())
&& response.getType().equals(OtaPackageType.SOFTWARE.name())) {
lwM2MClient.setSwUpdate(new LwM2mFwSwUpdate(lwM2MClient, OtaPackageType.SOFTWARE));
// clientContext.getProfile(lwM2MClient.getProfileId()).getPostAttributeLwm2mProfile();
lwM2MClient.getSwUpdate().setTypeUpdateByURL(false);
lwM2MClient.getSwUpdate().setRpcRequest(rpcRequest);
lwM2MClient.getSwUpdate().setCurrentVersion(response.getVersion());
lwM2MClient.getSwUpdate().setCurrentTitle(response.getTitle());

4
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportCoapResource.java

@ -37,9 +37,11 @@ import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.S
public class LwM2mTransportCoapResource extends AbstractLwm2mTransportResource {
private final ConcurrentMap<String, ObserveRelation> tokenToObserveRelationMap = new ConcurrentHashMap<>();
private final ConcurrentMap<String, AtomicInteger> tokenToObserveNotificationSeqMap = new ConcurrentHashMap<>();
private final LwM2mTransportMsgHandler handler;
public LwM2mTransportCoapResource(LwM2mTransportMsgHandler handler, String name) {
super(handler, name);
super(name);
this.handler = handler;
this.setObservable(true); // enable observing
this.addObserver(new CoapResourceObserver());
}

10
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportRequest.java

@ -163,12 +163,12 @@ public class LwM2mTransportRequest {
if (lwm2mClientRpcRequest != null) {
ResourceModel resourceModel = lwM2MClient.getResourceModel(targetIdVer, this.config.getModelProvider());
String errorMsg = resourceModel == null ? String.format("Path %s not found in object version", targetIdVer) : "SendRequest - null";
this.handler.sentRpcResponse(lwm2mClientRpcRequest, NOT_FOUND.getName(), errorMsg, LOG_LW2M_ERROR);
handler.sentRpcResponse(lwm2mClientRpcRequest, NOT_FOUND.getName(), errorMsg, LOG_LW2M_ERROR);
}
}
} else if (lwm2mClientRpcRequest != null) {
String errorMsg = String.format("Path %s not found in object version", targetIdVer);
this.handler.sentRpcResponse(lwm2mClientRpcRequest, NOT_FOUND.getName(), errorMsg, LOG_LW2M_ERROR);
handler.sentRpcResponse(lwm2mClientRpcRequest, NOT_FOUND.getName(), errorMsg, LOG_LW2M_ERROR);
}
} else {
switch (typeOper) {
@ -185,10 +185,10 @@ public class LwM2mTransportRequest {
}
String msg = String.format("%s: type operation %s paths - %s", LOG_LW2M_INFO,
typeOper.name(), paths);
this.handler.sendLogsToThingsboard(msg, registration.getId());
handler.sendLogsToThingsboard(msg, registration.getId());
if (lwm2mClientRpcRequest != null) {
String valueMsg = String.format("Paths - %s", paths);
this.handler.sentRpcResponse(lwm2mClientRpcRequest, CONTENT.name(), valueMsg, LOG_LW2M_VALUE);
handler.sentRpcResponse(lwm2mClientRpcRequest, CONTENT.name(), valueMsg, LOG_LW2M_VALUE);
}
break;
case OBSERVE_CANCEL:
@ -208,7 +208,7 @@ public class LwM2mTransportRequest {
break;
// lwm2mClientRpcRequest != null
case FW_UPDATE:
this.handler.getInfoFirmwareUpdate(lwM2MClient, lwm2mClientRpcRequest);
handler.getInfoFirmwareUpdate(lwM2MClient, lwm2mClientRpcRequest);
break;
}
}

5
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClient.java

@ -31,7 +31,6 @@ import org.eclipse.leshan.server.registration.Registration;
import org.eclipse.leshan.server.security.SecurityInfo;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.data.ota.OtaPackageType;
import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse;
import org.thingsboard.server.gen.transport.TransportProtos.SessionInfoProto;
import org.thingsboard.server.gen.transport.TransportProtos.TsKvProto;
@ -75,8 +74,6 @@ public class LwM2mClient implements Cloneable {
@Getter
private UUID deviceId;
@Getter
private UUID sessionId;
@Getter
private SessionInfoProto session;
@Getter
private UUID profileId;
@ -120,8 +117,6 @@ public class LwM2mClient implements Cloneable {
this.init = false;
this.queuedRequests = new ConcurrentLinkedQueue<>();
this.fwUpdate = new LwM2mFwSwUpdate(this, OtaPackageType.FIRMWARE);
this.swUpdate = new LwM2mFwSwUpdate(this, OtaPackageType.SOFTWARE);
if (this.credentials != null && this.credentials.hasDeviceInfo()) {
this.session = createSession(nodeId, sessionId, credentials);
this.deviceId = new UUID(session.getDeviceIdMSB(), session.getDeviceIdLSB());

2
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientContextImpl.java

@ -192,7 +192,7 @@ public class LwM2mClientContextImpl implements LwM2mClientContext {
@Override
public LwM2mClientProfile getProfile(Registration registration) {
return this.getProfiles().get(getOrRegister(registration).getProfileId());
return this.getProfiles().get(this.getOrRegister(registration).getProfileId());
}
@Override

6
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mFwSwUpdate.java

@ -32,12 +32,12 @@ import java.util.List;
import java.util.UUID;
import java.util.concurrent.CopyOnWriteArrayList;
import static org.eclipse.californium.core.coap.CoAP.ResponseCode.CONTENT;
import static org.thingsboard.server.common.data.ota.OtaPackageKey.STATE;
import static org.thingsboard.server.common.data.ota.OtaPackageType.FIRMWARE;
import static org.thingsboard.server.common.data.ota.OtaPackageType.SOFTWARE;
import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.UPDATING;
import static org.thingsboard.server.common.data.ota.OtaPackageUtil.getAttributeKey;
import static org.eclipse.californium.core.coap.CoAP.ResponseCode.CONTENT;
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;
@ -107,12 +107,16 @@ public class LwM2mFwSwUpdate {
@Getter
@Setter
private volatile Lwm2mClientRpcRequest rpcRequest;
@Getter
@Setter
private volatile boolean typeUpdateByURL;
public LwM2mFwSwUpdate(LwM2mClient lwM2MClient, OtaPackageType type) {
this.lwM2MClient = lwM2MClient;
this.pendingInfoRequestsStart = new CopyOnWriteArrayList<>();
this.type = type;
this.stateUpdate = null;
this.typeUpdateByURL = false;
this.initPathId();
}

58
ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-profile-transport-configuration.component.html

@ -20,20 +20,6 @@
<mat-tab label="{{ 'device-profile.lwm2m.model-tab' | translate }}">
<ng-template matTabContent>
<section [formGroup]="lwm2mDeviceProfileFormGroup">
<div *ngIf="false" class="mat-padding" style="padding-bottom: 0px">
<mat-form-field class="mat-block">
<mat-label>{{ 'device-profile.lwm2m.client-only-observe-after-connect-label' | translate }}</mat-label>
<mat-select formControlName="clientOnlyObserveAfterConnect"
matTooltip="{{ 'device-profile.lwm2m.client-only-observe-after-connect-tip' | translate:
{ count: +lwm2mDeviceProfileFormGroup.get('clientOnlyObserveAfterConnect').value } }}"
matTooltipPosition="above">
<mat-option value=1>{{ 'device-profile.lwm2m.client-only-observe-after-connect' | translate:
{count: 1} }}</mat-option>
<mat-option value=2>{{ 'device-profile.lwm2m.client-only-observe-after-connect' | translate:
{count: 2} }}</mat-option>
</mat-select>
</mat-form-field>
</div>
<div class="mat-padding" style="padding-top: 0">
<tb-profile-lwm2m-object-list
(addList)="addObjectsList($event)"
@ -51,7 +37,7 @@
</section>
</ng-template>
</mat-tab>
<mat-tab label="{{ 'device-profile.lwm2m.servers' | translate }}">
<mat-tab label="{{ 'device-profile.lwm2m.bootstrap-tab' | translate }}">
<ng-template matTabContent>
<section [formGroup]="lwm2mDeviceProfileFormGroup">
<div class="mat-padding">
@ -153,6 +139,48 @@
</section>
</ng-template>
</mat-tab>
<mat-tab label="{{ 'device-profile.lwm2m.others-tab' | translate }}">
<ng-template matTabContent>
<section [formGroup]="lwm2mDeviceProfileFormGroup">
<div *ngIf="false" class="mat-padding" style="padding-bottom: 0px">
<mat-form-field class="mat-block">
<mat-label>{{ 'device-profile.lwm2m.client-only-observe-after-connect-label' | translate }}</mat-label>
<mat-select formControlName="clientOnlyObserveAfterConnect"
matTooltip="{{ 'device-profile.lwm2m.client-only-observe-after-connect-tip' | translate:
{ count: +lwm2mDeviceProfileFormGroup.get('clientOnlyObserveAfterConnect').value } }}"
matTooltipPosition="above">
<mat-option value=1>{{ 'device-profile.lwm2m.client-only-observe-after-connect' | translate:
{count: 1} }}</mat-option>
<mat-option value=2>{{ 'device-profile.lwm2m.client-only-observe-after-connect' | translate:
{count: 2} }}</mat-option>
</mat-select>
</mat-form-field>
</div>
<div class="mat-padding" style="padding-bottom: 0px">
<mat-form-field class="mat-block">
<mat-label>{{ 'device-profile.lwm2m.fw-update-url-label' | translate }}</mat-label>
<mat-select formControlName="fwUpdateUrl">
<mat-option value=1>{{ 'device-profile.lwm2m.fw-update-url' | translate:
{count: 1} }}</mat-option>
<mat-option value=2>{{ 'device-profile.lwm2m.fw-update-url' | translate:
{count: 2} }}</mat-option>
<mat-option value=2>{{ 'device-profile.lwm2m.fw-update-url' | translate:
{count: 3} }}</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field class="mat-block">
<mat-label>{{ 'device-profile.lwm2m.sw-update-url-label' | translate }}</mat-label>
<mat-select formControlName="swUpdateUrl">
<mat-option value=1>{{ 'device-profile.lwm2m.sw-update-url' | translate:
{count: 1} }}</mat-option>
<mat-option value=2>{{ 'device-profile.lwm2m.sw-update-url' | translate:
{count: 2} }}</mat-option>
</mat-select>
</mat-form-field>
</div>
</section>
</ng-template>
</mat-tab>
<mat-tab label="{{ 'device-profile.lwm2m.config-json-tab' | translate }}">
<ng-template matTabContent>
<section [formGroup]="lwm2mDeviceConfigFormGroup" class="mat-padding">

15
ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-profile-transport-configuration.component.ts

@ -80,7 +80,6 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
constructor(private fb: FormBuilder,
private deviceProfileService: DeviceProfileService) {
this.lwm2mDeviceProfileFormGroup = this.fb.group({
clientOnlyObserveAfterConnect: [1, []],
objectIds: [null, Validators.required],
observeAttrTelemetry: [null, Validators.required],
shortId: [null, Validators.required],
@ -90,6 +89,9 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
binding:[],
bootstrapServer: [null, Validators.required],
lwm2mServer: [null, Validators.required],
clientOnlyObserveAfterConnect: [1, []],
fwUpdateUrl: [1, []],
swUpdateUrl: [1, []],
});
this.lwm2mDeviceConfigFormGroup = this.fb.group({
configurationJson: [null, Validators.required]
@ -150,7 +152,6 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
private updateWriteValue = (value: ModelValue): void => {
this.lwm2mDeviceProfileFormGroup.patchValue({
clientOnlyObserveAfterConnect: this.configurationValue.clientLwM2mSettings.clientOnlyObserveAfterConnect,
objectIds: value,
observeAttrTelemetry: this.getObserveAttrTelemetryObjects(value.objectsList),
shortId: this.configurationValue.bootstrap.servers.shortId,
@ -159,7 +160,10 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
notifIfDisabled: this.configurationValue.bootstrap.servers.notifIfDisabled,
binding: this.configurationValue.bootstrap.servers.binding,
bootstrapServer: this.configurationValue.bootstrap.bootstrapServer,
lwm2mServer: this.configurationValue.bootstrap.lwm2mServer
lwm2mServer: this.configurationValue.bootstrap.lwm2mServer,
clientOnlyObserveAfterConnect: this.configurationValue.clientLwM2mSettings.clientOnlyObserveAfterConnect,
fwUpdateUrl: this.configurationValue.clientLwM2mSettings.fwUpdateUrl,
swUpdateUrl: this.configurationValue.clientLwM2mSettings.swUpdateUrl
},
{emitEvent: false});
}
@ -181,8 +185,6 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
private updateDeviceProfileValue(config): void {
if (this.lwm2mDeviceProfileFormGroup.valid) {
this.configurationValue.clientLwM2mSettings.clientOnlyObserveAfterConnect =
config.clientOnlyObserveAfterConnect;
this.updateObserveAttrTelemetryFromGroupToJson(config.observeAttrTelemetry.clientLwM2M);
this.configurationValue.bootstrap.bootstrapServer = config.bootstrapServer;
this.configurationValue.bootstrap.lwm2mServer = config.lwm2mServer;
@ -192,6 +194,9 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
bootstrapServers.defaultMinPeriod = config.defaultMinPeriod;
bootstrapServers.notifIfDisabled = config.notifIfDisabled;
bootstrapServers.binding = config.binding;
this.configurationValue.clientLwM2mSettings.clientOnlyObserveAfterConnect = config.clientOnlyObserveAfterConnect;
this.configurationValue.clientLwM2mSettings.fwUpdateUrl = config.fwUpdateUrl;
this.configurationValue.clientLwM2mSettings.swUpdateUrl = config.swUpdateUrl;
this.upDateJsonAllConfig();
this.updateModel();
}

8
ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-profile-config.models.ts

@ -166,7 +166,9 @@ export interface Lwm2mProfileConfigModels {
}
export interface ClientLwM2mSettings {
clientOnlyObserveAfterConnect: number;
clientOnlyObserveAfterConnect: string;
fwUpdateUrl: string;
swUpdateUrl: string;
}
export interface ObservableAttributes {
@ -236,7 +238,9 @@ export function getDefaultProfileConfig(hostname?: any): Lwm2mProfileConfigModel
function getDefaultProfileClientLwM2mSettingsConfig(): ClientLwM2mSettings {
return {
clientOnlyObserveAfterConnect: 1
clientOnlyObserveAfterConnect: "1",
fwUpdateUrl: "1",
swUpdateUrl: "1"
};
}

12
ui-ngx/src/assets/locale/locale.constant-en_US.json

@ -1186,9 +1186,6 @@
"device-profile-file": "Device profile file",
"invalid-device-profile-file-error": "Unable to import device profile: Invalid device profile data structure.",
"lwm2m": {
"client-only-observe-after-connect-label": "Strategy",
"client-only-observe-after-connect": "{ count, plural, 1 {1: Only Observe Request to the client after the initial connection} other {2: Read All Resources & Observe Request to the client after registration} }",
"client-only-observe-after-connect-tip": "{ count, plural, 1 {Strategy 1: After the initial connection of the LWM2M Client, the server sends Observe resources Request to the client, those resources that are marked as observation in the Device profile and which exist on the LWM2M client.} other {Strategy 2: After the registration, request the client to read all the resource values for all objects that the LWM2M client has,\n then execute: the server sends Observe resources Request to the client, those resources that are marked as observation in the Device profile and which exist on the LWM2M client.} }",
"object-list": "Object list",
"object-list-empty": "No objects selected.",
"no-objects-matching": "No objects matching '{{object}}' were found.",
@ -1236,6 +1233,7 @@
"default-min-period": "Minimum Period between two notifications (sec)",
"notif-if-disabled": "Notification Storing When Disabled or Offline",
"binding": "Binding",
"bootstrap-tab": "Bootstrap",
"bootstrap-server": "Bootstrap Server",
"lwm2m-server": "LwM2M Server",
"server-host": "Host",
@ -1248,6 +1246,14 @@
"client-hold-off-time-tip": "Client Hold Off Time for use with a Bootstrap-Server only",
"bootstrap-server-account-timeout": "Account after the timeout",
"bootstrap-server-account-timeout-tip": "Bootstrap-Server Account after the timeout value given by this resource.",
"others-tab": "Other settings...",
"client-only-observe-after-connect-label": "Strategy",
"client-only-observe-after-connect": "{ count, plural, 1 {1: Only Observe Request to the client after the initial connection} other {2: Read All Resources & Observe Request to the client after registration} }",
"client-only-observe-after-connect-tip": "{ count, plural, 1 {Strategy 1: After the initial connection of the LWM2M Client, the server sends Observe resources Request to the client, those resources that are marked as observation in the Device profile and which exist on the LWM2M client.} other {Strategy 2: After the registration, request the client to read all the resource values for all objects that the LWM2M client has,\n then execute: the server sends Observe resources Request to the client, those resources that are marked as observation in the Device profile and which exist on the LWM2M client.} }",
"fw-update-url-label": "Firmware update strategy",
"fw-update-url": "{ count, plural, 1 {Push firmware update as binary file using Object 5 and Resource 0 (Package).} 2 {Push firmware update as binary file using Object 5 and Resource 0 (Package).} other {Push firmware update as binary file using Object 19 and Resource 0 (Data).} }",
"sw-update-url-label": "Software update strategy",
"sw-update-url": "{ count, plural, 1 {Push binary file using Object 9 and Resource 2 (Package).} other {Auto-generate unique CoAP URL to download the package and push software update using Object 9 and Resource 3 (Package URI).} }",
"config-json-tab": "Json Config Profile Device"
}
},

Loading…
Cancel
Save