Browse Source

fix_lwm2m: do not send resources for reading if necessary

pull/14052/head
nickAS21 8 months ago
parent
commit
1c28ce6182
  1. 2
      application/src/main/java/org/thingsboard/server/service/device/DeviceBulkImportService.java
  2. 61
      application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/AbstractRpcLwM2MIntegrationTest.java
  3. 92
      application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationInitReadCompositeAllTest.java
  4. 92
      application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationInitReadCompositeByObjectTest.java
  5. 3
      common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/TelemetryMappingConfiguration.java
  6. 2
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/composite/TbLwM2MObserveCompositeCallback.java
  7. 51
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/uplink/DefaultLwM2mUplinkMsgHandler.java
  8. 5
      ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-profile-transport-configuration.component.html
  9. 8
      ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-profile-transport-configuration.component.ts
  10. 1
      ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-profile-config.models.ts
  11. 4
      ui-ngx/src/assets/locale/locale.constant-en_US.json

2
application/src/main/java/org/thingsboard/server/service/device/DeviceBulkImportService.java

@ -259,7 +259,7 @@ public class DeviceBulkImportService extends AbstractBulkImportService<Device> {
Lwm2mDeviceProfileTransportConfiguration transportConfiguration = new Lwm2mDeviceProfileTransportConfiguration();
transportConfiguration.setBootstrap(Collections.emptyList());
transportConfiguration.setClientLwM2mSettings(new OtherConfiguration(false,1, 1, 1, PowerMode.DRX, null, null, null, null, null, V1_0.toString()));
transportConfiguration.setObserveAttr(new TelemetryMappingConfiguration(Collections.emptyMap(), Collections.emptySet(), Collections.emptySet(), Collections.emptySet(), Collections.emptyMap(), SINGLE));
transportConfiguration.setObserveAttr(new TelemetryMappingConfiguration(Collections.emptyMap(), Collections.emptySet(), Collections.emptySet(), Collections.emptySet(), Collections.emptyMap(), false, SINGLE));
DeviceProfileData deviceProfileData = new DeviceProfileData();
DefaultDeviceProfileConfiguration configuration = new DefaultDeviceProfileConfiguration();

61
application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/AbstractRpcLwM2MIntegrationTest.java

@ -115,6 +115,10 @@ public abstract class AbstractRpcLwM2MIntegrationTest extends AbstractLwM2MInteg
initRpc(0);
} else if (this.getClass().getSimpleName().equals("RpcLwm2mIntegrationReadCollectedValueTest")) {
initRpc(3303);
} else if (this.getClass().getSimpleName().equals("RpcLwm2mIntegrationInitReadCompositeAllTest")) {
initRpc(2);
}else if (this.getClass().getSimpleName().equals("RpcLwm2mIntegrationInitReadCompositeByObjectTest")) {
initRpc(3);
} else {
initRpc(1);
}
@ -221,10 +225,67 @@ public abstract class AbstractRpcLwM2MIntegrationTest extends AbstractLwM2MInteg
" ],\n" +
" \"attributeLwm2m\": {}\n" +
" }";
String INIT_READ_TELEMETRY_ATTRIBUTE_AS_OBSERVE_STRATEGY_ALL =
" {\n" +
" \"keyName\": {\n" +
" \"/3_1.2/0/9\": \"batteryLevel\",\n" +
" \"/3_1.2/0/20\": \"batteryStatus\",\n" +
" \"/19_1.1/0/2\": \"dataCreationTime\",\n" +
" \"/5_1.2/0/6\": \"pkgname\",\n" +
" \"/5_1.2/0/7\": \"pkgversion\",\n" +
" \"/5_1.2/0/9\": \"firmwareUpdateDeliveryMethod\"\n" +
" },\n" +
" \"observe\": [\n" +
" \"/3_1.2/0/20\"\n" +
" ],\n" +
" \"attribute\": [\n" +
" \"/5_1.2/0/6\",\n" +
" \"/5_1.2/0/7\"\n" +
" ],\n" +
" \"telemetry\": [\n" +
" \"/3_1.2/0/9\",\n" +
" \"/3_1.2/0/20\",\n" +
" \"/5_1.2/0/9\",\n" +
" \"/19_1.1/0/2\"\n" +
" ],\n" +
" \"attributeLwm2m\": {},\n" +
" \"initAttrTelAsObsStrategy\": true,\n" +
" \"observeStrategy\": 1\n" +
" }";
String INIT_READ_TELEMETRY_ATTRIBUTE_AS_OBSERVE_STRATEGY_BY_OBJECT =
" {\n" +
" \"keyName\": {\n" +
" \"/3_1.2/0/9\": \"batteryLevel\",\n" +
" \"/3_1.2/0/20\": \"batteryStatus\",\n" +
" \"/19_1.1/0/2\": \"dataCreationTime\",\n" +
" \"/5_1.2/0/6\": \"pkgname\",\n" +
" \"/5_1.2/0/7\": \"pkgversion\",\n" +
" \"/5_1.2/0/9\": \"firmwareUpdateDeliveryMethod\"\n" +
" },\n" +
" \"observe\": [\n" +
" \"/3_1.2/0/9\"\n" +
" ],\n" +
" \"attribute\": [\n" +
" \"/5_1.2/0/6\",\n" +
" \"/5_1.2/0/7\"\n" +
" ],\n" +
" \"telemetry\": [\n" +
" \"/3_1.2/0/9\",\n" +
" \"/3_1.2/0/20\",\n" +
" \"/5_1.2/0/9\",\n" +
" \"/19_1.1/0/2\"\n" +
" ],\n" +
" \"attributeLwm2m\": {},\n" +
" \"initAttrTelAsObsStrategy\": true,\n" +
" \"observeStrategy\": 2\n" +
" }";
CONFIG_PROFILE_WITH_PARAMS_RPC =
switch (typeConfigProfile) {
case 0 -> ATTRIBUTES_TELEMETRY_WITH_PARAMS_RPC_WITH_OBSERVE;
case 1 -> TELEMETRY_WITH_PARAMS_RPC_WITHOUT_OBSERVE;
case 2 -> INIT_READ_TELEMETRY_ATTRIBUTE_AS_OBSERVE_STRATEGY_ALL;
case 3 -> INIT_READ_TELEMETRY_ATTRIBUTE_AS_OBSERVE_STRATEGY_BY_OBJECT;
case 3303 -> TELEMETRY_WITH_PARAMS_RPC_COLLECTED_VALUE;
default -> throw new IllegalStateException("Unexpected value: " + typeConfigProfile);
};

92
application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationInitReadCompositeAllTest.java

@ -0,0 +1,92 @@
/**
* Copyright © 2016-2025 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.rpc.sql;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.node.ObjectNode;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.thingsboard.server.transport.lwm2m.rpc.AbstractRpcLwM2MIntegrationTest;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.awaitility.Awaitility.await;
import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.OBJECT_INSTANCE_ID_0;
import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.RESOURCE_ID_2;
import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.RESOURCE_ID_6;
import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.RESOURCE_ID_7;
import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.RESOURCE_ID_9;
@Slf4j
public class RpcLwm2mIntegrationInitReadCompositeAllTest extends AbstractRpcLwM2MIntegrationTest {
/**
" \"/3_1.2/0/9\": \"batteryLevel\", - Telemetry
" \"/3_1.2/0/20\": \"batteryStatus\" - Observe, Telemetry
" \"/5_1.2/0/6\": \"pkgname\" - Attributes
" \"/5_1.2/0/7\": \"pkgversion\" - Attributes
" \"/5_1.2/0/9\": \"firmwareUpdateDeliveryMethod\"\ - Telemetry
" \"/19_1.1/0/2\": \"dataCreationTime\" - Telemetry
* "observeStrategy": 1
*/
@Test
public void testInitReadCompositeAsObserveStrategyCompositeAll() throws Exception {
// init test
String RESOURCE_3_9 = "batteryLevel";
String RESOURCE_3_20 = "batteryStatus";
String RESOURCE_5_6 = "pkgname";
String RESOURCE_5_7 = "pkgversion";
String RESOURCE_5_9 = "firmwareUpdateDeliveryMethod";
String RESOURCE_19_2 = "dataCreationTime";
String idVwr_3_0_20 = idVer_3_0_9 = objectIdVer_3 + "/" + OBJECT_INSTANCE_ID_0 + "/" + 20;
String IdVer5_0_6 = objectInstanceIdVer_5 + "/" + RESOURCE_ID_6;
String IdVer5_0_7 = objectInstanceIdVer_5 + "/" + RESOURCE_ID_7;
String IdVer5_0_9 = objectInstanceIdVer_5 + "/" + RESOURCE_ID_9;
String idVer_19_0_2 = objectIdVer_19 + "/" + OBJECT_INSTANCE_ID_0 + "/" + RESOURCE_ID_2;
countUpdateAttrTelemetryResource(idVer_3_0_9);
countUpdateAttrTelemetryResource(idVwr_3_0_20);
countUpdateAttrTelemetryResource(IdVer5_0_6);
countUpdateAttrTelemetryResource(IdVer5_0_7);
countUpdateAttrTelemetryResource(IdVer5_0_9);
countUpdateAttrTelemetryResource(idVer_19_0_2);
AtomicReference<ObjectNode> actualValues = new AtomicReference<>();
await().atMost(40, SECONDS).until(() -> {
actualValues.set(doGetAsync(
"/api/plugins/telemetry/DEVICE/" + lwM2MTestClient.getDeviceIdStr() + "/values/timeseries?keys="
+ RESOURCE_3_9 + "," + RESOURCE_3_20 + "," + RESOURCE_5_9 + "," + RESOURCE_19_2, ObjectNode.class));
return actualValues.get() != null && !actualValues.get().isEmpty()
&& !actualValues.get().get(RESOURCE_3_9).isEmpty()
&& !actualValues.get().get(RESOURCE_3_20).isEmpty()
&& !actualValues.get().get(RESOURCE_5_9).isEmpty()
&& !actualValues.get().get(RESOURCE_19_2).isEmpty();
});
AtomicReference<List<String>> actualKeys =new AtomicReference<>();
await().atMost(40, SECONDS).until(() -> {
actualKeys.set(doGetAsyncTyped("/api/plugins/telemetry/DEVICE/" + lwM2MTestClient.getDeviceIdStr() + "/keys/attributes/CLIENT_SCOPE", new TypeReference<>() {
}));
return actualKeys.get() != null && !actualKeys.get().isEmpty() && !actualKeys.get().isEmpty()
&& actualKeys.get().contains(RESOURCE_5_6)&& actualKeys.get().contains(RESOURCE_5_7);
});
}
}

92
application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationInitReadCompositeByObjectTest.java

@ -0,0 +1,92 @@
/**
* Copyright © 2016-2025 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.rpc.sql;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.node.ObjectNode;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.thingsboard.server.transport.lwm2m.rpc.AbstractRpcLwM2MIntegrationTest;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.awaitility.Awaitility.await;
import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.OBJECT_INSTANCE_ID_0;
import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.RESOURCE_ID_2;
import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.RESOURCE_ID_6;
import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.RESOURCE_ID_7;
import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.RESOURCE_ID_9;
@Slf4j
public class RpcLwm2mIntegrationInitReadCompositeByObjectTest extends AbstractRpcLwM2MIntegrationTest {
/**
" \"/3_1.2/0/9\": \"batteryLevel\", - Telemetry
" \"/3_1.2/0/20\": \"batteryStatus\" - Observe, Telemetry
" \"/5_1.2/0/6\": \"pkgname\" - Attributes
" \"/5_1.2/0/7\": \"pkgversion\" - Attributes
" \"/5_1.2/0/9\": \"firmwareUpdateDeliveryMethod\"\ - Telemetry
" \"/19_1.1/0/2\": \"dataCreationTime\" - Telemetry
* "observeStrategy": 2
*/
@Test
public void testInitReadCompositeAsObserveStrategyCompositeByObject() throws Exception {
// init test
String RESOURCE_3_9 = "batteryLevel";
String RESOURCE_3_20 = "batteryStatus";
String RESOURCE_5_6 = "pkgname";
String RESOURCE_5_7 = "pkgversion";
String RESOURCE_5_9 = "firmwareUpdateDeliveryMethod";
String RESOURCE_19_2 = "dataCreationTime";
String idVwr_3_0_20 = idVer_3_0_9 = objectIdVer_3 + "/" + OBJECT_INSTANCE_ID_0 + "/" + 20;
String IdVer5_0_6 = objectInstanceIdVer_5 + "/" + RESOURCE_ID_6;
String IdVer5_0_7 = objectInstanceIdVer_5 + "/" + RESOURCE_ID_7;
String IdVer5_0_9 = objectInstanceIdVer_5 + "/" + RESOURCE_ID_9;
String idVer_19_0_2 = objectIdVer_19 + "/" + OBJECT_INSTANCE_ID_0 + "/" + RESOURCE_ID_2;
countUpdateAttrTelemetryResource(idVer_3_0_9);
countUpdateAttrTelemetryResource(idVwr_3_0_20);
countUpdateAttrTelemetryResource(IdVer5_0_6);
countUpdateAttrTelemetryResource(IdVer5_0_7);
countUpdateAttrTelemetryResource(IdVer5_0_9);
countUpdateAttrTelemetryResource(idVer_19_0_2);
AtomicReference<ObjectNode> actualValues = new AtomicReference<>();
await().atMost(40, SECONDS).until(() -> {
actualValues.set(doGetAsync(
"/api/plugins/telemetry/DEVICE/" + lwM2MTestClient.getDeviceIdStr() + "/values/timeseries?keys="
+ RESOURCE_3_9 + "," + RESOURCE_3_20 + "," + RESOURCE_5_9 + "," + RESOURCE_19_2, ObjectNode.class));
return actualValues.get() != null && !actualValues.get().isEmpty()
&& !actualValues.get().get(RESOURCE_3_9).isEmpty()
&& !actualValues.get().get(RESOURCE_3_20).isEmpty()
&& !actualValues.get().get(RESOURCE_5_9).isEmpty()
&& !actualValues.get().get(RESOURCE_19_2).isEmpty();
});
AtomicReference<List<String>> actualKeys =new AtomicReference<>();
await().atMost(40, SECONDS).until(() -> {
actualKeys.set(doGetAsyncTyped("/api/plugins/telemetry/DEVICE/" + lwM2MTestClient.getDeviceIdStr() + "/keys/attributes/CLIENT_SCOPE", new TypeReference<>() {
}));
return actualKeys.get() != null && !actualKeys.get().isEmpty() && !actualKeys.get().isEmpty()
&& actualKeys.get().contains(RESOURCE_5_6)&& actualKeys.get().contains(RESOURCE_5_7);
});
}
}

3
common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/TelemetryMappingConfiguration.java

@ -36,6 +36,7 @@ public class TelemetryMappingConfiguration implements Serializable {
private Set<String> attribute;
private Set<String> telemetry;
private Map<String, ObjectAttributes> attributeLwm2m;
private Boolean initAttrTelAsObsStrategy;
private TelemetryObserveStrategy observeStrategy;
@JsonCreator
@ -45,6 +46,7 @@ public class TelemetryMappingConfiguration implements Serializable {
@JsonProperty("attribute") Set<String> attribute,
@JsonProperty("telemetry") Set<String> telemetry,
@JsonProperty("attributeLwm2m") Map<String, ObjectAttributes> attributeLwm2m,
@JsonProperty("initAttrTelAsObsStrategy") Boolean initAttrTelAsObsStrategy,
@JsonProperty("observeStrategy") TelemetryObserveStrategy observeStrategy) {
this.keyName = keyName != null ? keyName : Collections.emptyMap();
@ -52,6 +54,7 @@ public class TelemetryMappingConfiguration implements Serializable {
this.attribute = attribute != null ? attribute : Collections.emptySet();
this.telemetry = telemetry != null ? telemetry : Collections.emptySet();
this.attributeLwm2m = attributeLwm2m != null ? attributeLwm2m : Collections.emptyMap();
this.initAttrTelAsObsStrategy = initAttrTelAsObsStrategy != null ? initAttrTelAsObsStrategy : false;
this.observeStrategy = observeStrategy != null ? observeStrategy : TelemetryObserveStrategy.SINGLE;
}
}

2
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/composite/TbLwM2MObserveCompositeCallback.java

@ -23,6 +23,8 @@ import org.thingsboard.server.transport.lwm2m.server.downlink.TbLwM2MUplinkTarge
import org.thingsboard.server.transport.lwm2m.server.log.LwM2MTelemetryLogService;
import org.thingsboard.server.transport.lwm2m.server.uplink.LwM2mUplinkMsgHandler;
import java.util.concurrent.CountDownLatch;
@Slf4j
public class TbLwM2MObserveCompositeCallback extends TbLwM2MUplinkTargetedCallback<ObserveCompositeRequest, ObserveCompositeResponse> {

51
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/uplink/DefaultLwM2mUplinkMsgHandler.java

@ -94,6 +94,8 @@ import org.thingsboard.server.transport.lwm2m.server.downlink.TbLwM2MWriteAttrib
import org.thingsboard.server.transport.lwm2m.server.downlink.TbLwM2MWriteAttributesRequest;
import org.thingsboard.server.transport.lwm2m.server.downlink.composite.TbLwM2MObserveCompositeCallback;
import org.thingsboard.server.transport.lwm2m.server.downlink.composite.TbLwM2MObserveCompositeRequest;
import org.thingsboard.server.transport.lwm2m.server.downlink.composite.TbLwM2MReadCompositeCallback;
import org.thingsboard.server.transport.lwm2m.server.downlink.composite.TbLwM2MReadCompositeRequest;
import org.thingsboard.server.transport.lwm2m.server.log.LwM2MTelemetryLogService;
import org.thingsboard.server.transport.lwm2m.server.model.LwM2MModelConfig;
import org.thingsboard.server.transport.lwm2m.server.model.LwM2MModelConfigService;
@ -483,9 +485,9 @@ public class DefaultLwM2mUplinkMsgHandler extends LwM2MExecutorAwareService impl
private void initClientTelemetry(LwM2mClient lwM2MClient) {
Lwm2mDeviceProfileTransportConfiguration profile = clientContext.getProfile(lwM2MClient.getRegistration());
Set<String> supportedObjects = clientContext.getSupportedIdVerInClient(lwM2MClient);
if (supportedObjects != null && supportedObjects.size() > 0) {
this.sendReadRequests(lwM2MClient, profile, supportedObjects);
if (supportedObjects != null && !supportedObjects.isEmpty()) {
this.sendInitObserveRequests(lwM2MClient, profile, supportedObjects);
this.sendReadRequests(lwM2MClient, profile, supportedObjects);
this.sendWriteAttributeRequests(lwM2MClient, profile, supportedObjects);
// Removed. Used only for debug.
// this.sendDiscoverRequests(lwM2MClient, profile, supportedObjects);
@ -495,14 +497,30 @@ public class DefaultLwM2mUplinkMsgHandler extends LwM2MExecutorAwareService impl
private void sendReadRequests(LwM2mClient lwM2MClient, Lwm2mDeviceProfileTransportConfiguration profile, Set<String> supportedObjects) {
try {
Set<String> targetIds = new HashSet<>(profile.getObserveAttr().getAttribute());
Boolean initAttrTelAsObsStrategy = profile.getObserveAttr().getInitAttrTelAsObsStrategy();
targetIds.addAll(profile.getObserveAttr().getTelemetry());
targetIds = diffSets(profile.getObserveAttr().getObserve(), targetIds);
targetIds = targetIds.stream().filter(target -> isSupportedTargetId(supportedObjects, target)).collect(Collectors.toSet());
CountDownLatch latch = new CountDownLatch(targetIds.size());
targetIds.forEach(versionedId -> sendReadRequest(lwM2MClient, versionedId,
new TbLwM2MLatchCallback<>(latch, new TbLwM2MReadCallback(this, logService, lwM2MClient, versionedId))));
latch.await(config.getTimeout(), TimeUnit.MILLISECONDS);
if (!targetIds.isEmpty()) {
TelemetryObserveStrategy observeStrategy = profile.getObserveAttr().getObserveStrategy();
long timeoutMs = config.getTimeout();
if (initAttrTelAsObsStrategy && observeStrategy != SINGLE) {
switch (observeStrategy) {
case COMPOSITE_ALL -> {
sendReadCompositeRequest(lwM2MClient, targetIds.toArray(new String[0]));
}
case COMPOSITE_BY_OBJECT -> {
Map<Integer, String[]> versionedObjectIds = groupByObjectIdVersionedIds(targetIds);
versionedObjectIds.forEach((k, v) -> sendReadCompositeRequest(lwM2MClient, v));
}
}
} else {
CountDownLatch latch = new CountDownLatch(targetIds.size());
targetIds.forEach(versionedId -> sendReadSingleRequest(lwM2MClient, versionedId,
new TbLwM2MLatchCallback<>(latch, new TbLwM2MReadCallback(this, logService, lwM2MClient, versionedId))));
latch.await(timeoutMs, TimeUnit.MILLISECONDS);
}
}
} catch (InterruptedException e) {
log.error("[{}] Failed to await Read requests!", lwM2MClient.getEndpoint(), e);
} catch (Exception e) {
@ -529,17 +547,11 @@ public class DefaultLwM2mUplinkMsgHandler extends LwM2MExecutorAwareService impl
if (!completed) log.trace("[{}] Timeout occurred during SINGLE observe init", lwM2MClient.getEndpoint());
}
case COMPOSITE_ALL -> {
CountDownLatch latch = new CountDownLatch(targetIds.size());
sendObserveCompositeRequest(lwM2MClient, targetIds.toArray(new String[0]));
boolean completed = latch.await(timeoutMs, TimeUnit.MILLISECONDS);
if (!completed) log.trace("[{}] Timeout occurred during COMPOSITE_ALL observe init", lwM2MClient.getEndpoint());
}
case COMPOSITE_BY_OBJECT -> {
Map<Integer, String[]> versionedObjectIds = groupByObjectIdVersionedIds(targetIds);
CountDownLatch latch = new CountDownLatch(versionedObjectIds.size());
versionedObjectIds.forEach((k, v) -> sendObserveCompositeRequest(lwM2MClient, v));
boolean completed = latch.await(timeoutMs, TimeUnit.MILLISECONDS);
if (!completed) log.trace("[{}] Timeout occurred during COMPOSITE_BY_OBJECT observe init", lwM2MClient.getEndpoint());
}
}
}
@ -562,23 +574,22 @@ public class DefaultLwM2mUplinkMsgHandler extends LwM2MExecutorAwareService impl
}
}
private void sendReadRequest(LwM2mClient lwM2MClient, String versionedId) {
sendReadRequest(lwM2MClient, versionedId, new TbLwM2MReadCallback(this, logService, lwM2MClient, versionedId));
}
private void sendReadRequest(LwM2mClient lwM2MClient, String versionedId, DownlinkRequestCallback<ReadRequest, ReadResponse> callback) {
private void sendReadSingleRequest(LwM2mClient lwM2MClient, String versionedId, DownlinkRequestCallback<ReadRequest, ReadResponse> callback) {
TbLwM2MReadRequest request = TbLwM2MReadRequest.builder().versionedId(versionedId).timeout(clientContext.getRequestTimeout(lwM2MClient)).build();
defaultLwM2MDownlinkMsgHandler.sendReadRequest(lwM2MClient, request, callback);
}
private void sendObserveRequest(LwM2mClient lwM2MClient, String versionedId) {
sendObserveRequest(lwM2MClient, versionedId, new TbLwM2MObserveCallback(this, logService, lwM2MClient, versionedId));
private void sendReadCompositeRequest(LwM2mClient lwM2MClient, String[] versionedIds) {
TbLwM2MReadCompositeRequest request = TbLwM2MReadCompositeRequest.builder().versionedIds(versionedIds).timeout(clientContext.getRequestTimeout(lwM2MClient)).build();
var mainCallback = new TbLwM2MReadCompositeCallback(this, logService, lwM2MClient, versionedIds);
defaultLwM2MDownlinkMsgHandler.sendReadCompositeRequest(lwM2MClient, request, mainCallback );
}
private void sendObserveRequest(LwM2mClient lwM2MClient, String versionedId, DownlinkRequestCallback<ObserveRequest, ObserveResponse> callback) {
TbLwM2MObserveRequest request = TbLwM2MObserveRequest.builder().versionedId(versionedId).timeout(clientContext.getRequestTimeout(lwM2MClient)).build();
defaultLwM2MDownlinkMsgHandler.sendObserveRequest(lwM2MClient, request, callback);
}
private void sendObserveCompositeRequest(LwM2mClient lwM2MClient, String[] versionedIds) {
TbLwM2MObserveCompositeRequest request = TbLwM2MObserveCompositeRequest.builder().versionedIds(versionedIds).timeout(clientContext.getRequestTimeout(lwM2MClient)).build();

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

@ -25,6 +25,11 @@
(removeList)="removeObjectsList($event)"
formControlName="objectIds">
</tb-profile-lwm2m-object-list>
<mat-checkbox formControlName="initAttrTelAsObsStrategy">
<span tb-hint-tooltip-icon="{{ 'device-profile.lwm2m.init-attr-tel-as-obs-strategy-hint' | translate }}">
{{ 'device-profile.lwm2m.init-attr-tel-as-obs-strategy' | translate }}
</span>
</mat-checkbox>
<mat-form-field class="mat-block">
<mat-label translate>device-profile.lwm2m.observe-strategy.observe-strategy</mat-label>
<mat-select formControlName="observeStrategy">

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

@ -108,6 +108,7 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
bootstrapServerUpdateEnable: [false],
bootstrap: [[]],
observeStrategy: [null, []],
initAttrTelAsObsStrategy: [false],
clientLwM2mSettings: this.fb.group({
clientOnlyObserveAfterConnect: [1, []],
useObject19ForOtaInfo: [false],
@ -183,6 +184,10 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
takeUntil(this.destroy$)
).subscribe(value => this.updateObserveStrategy(value));
this.lwm2mDeviceProfileFormGroup.get('initAttrTelAsObsStrategy').valueChanges.pipe(
takeUntil(this.destroy$)
).subscribe(value => this.configurationValue.observeAttr.initAttrTelAsObsStrategy = value);
this.lwm2mDeviceProfileFormGroup.valueChanges.pipe(
takeUntil(this.destroy$)
).subscribe((value) => {
@ -272,6 +277,7 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
bootstrap: this.configurationValue.bootstrap,
bootstrapServerUpdateEnable: this.configurationValue.bootstrapServerUpdateEnable || false,
observeStrategy: this.configurationValue.observeAttr.observeStrategy || ObserveStrategy.SINGLE,
initAttrTelAsObsStrategy: this.configurationValue.observeAttr.initAttrTelAsObsStrategy ?? false,
clientLwM2mSettings: {
clientOnlyObserveAfterConnect: this.configurationValue.clientLwM2mSettings.clientOnlyObserveAfterConnect,
useObject19ForOtaInfo: this.configurationValue.clientLwM2mSettings.useObject19ForOtaInfo ?? false,
@ -440,6 +446,7 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
const attributes: any = {};
const keyNameNew = {};
const observeStrategyValue = this.lwm2mDeviceProfileFormGroup.get('observeStrategy').value;
const initAttrTelAsObsStrategyValue = this.lwm2mDeviceProfileFormGroup.get('initAttrTelAsObsStrategy').value;
const observeJson: ObjectLwM2M[] = JSON.parse(JSON.stringify(val));
observeJson.forEach(obj => {
if (isDefinedAndNotNull(obj.attributes) && !isEmpty(obj.attributes)) {
@ -481,6 +488,7 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
telemetry: telemetryArray,
keyName: this.sortObjectKeyPathJson(KEY_NAME, keyNameNew),
attributeLwm2m: attributes,
initAttrTelAsObsStrategy: initAttrTelAsObsStrategyValue,
observeStrategy: observeStrategyValue
};
}

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

@ -223,6 +223,7 @@ export interface ObservableAttributes {
keyName: {};
attributeLwm2m: AttributesNameValueMap;
observeStrategy: ObserveStrategy;
initAttrTelAsObsStrategy?: boolean;
}
export function getDefaultProfileObserveAttrConfig(): ObservableAttributes {

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

@ -2394,7 +2394,9 @@
"composite-all-description": "All resources are observed with a single Composite Observe request (more efficient, less flexible)",
"composite-by-object": "Composite by objects",
"composite-by-object-description": "Resources are grouped by object type and observed using separate Composite Observe requests (balanced approach)"
}
},
"init-attr-tel-as-obs-strategy": "Initializing attributes and telemetry as an Observe Strategy",
"init-attr-tel-as-obs-strategy-hint": "If the value is false - when initializing attributes and telemetry reading their values one by one\nIf the value is true - when initializing attributes and telemetry reading their values as indicated by the observation strategy"
},
"snmp": {
"add-communication-config": "Add communication config",

Loading…
Cancel
Save