lwm2m: fix bug test sendCollected
This commit is contained in:
		
							parent
							
								
									bb945e2540
								
							
						
					
					
						commit
						4b53e81daf
					
				@ -137,6 +137,8 @@ public class LwM2MTestClient {
 | 
			
		||||
    private Map<LwM2MClientState, Integer> clientDtlsCid;
 | 
			
		||||
    private LwM2mUplinkMsgHandler defaultLwM2mUplinkMsgHandlerTest;
 | 
			
		||||
    private LwM2mClientContext clientContext;
 | 
			
		||||
    private LwM2mTemperatureSensor lwM2mTemperatureSensor12;
 | 
			
		||||
 | 
			
		||||
    public void init(Security security, Security securityBs, int port, boolean isRpc,
 | 
			
		||||
                     LwM2mUplinkMsgHandler defaultLwM2mUplinkMsgHandler,
 | 
			
		||||
                     LwM2mClientContext clientContext, boolean isWriteAttribute, Integer cIdLength, boolean queueMode,
 | 
			
		||||
@ -189,7 +191,7 @@ public class LwM2MTestClient {
 | 
			
		||||
        locationParams.getPos();
 | 
			
		||||
        initializer.setInstancesForObject(LOCATION, new LwM2mLocation(locationParams.getLatitude(), locationParams.getLongitude(), locationParams.getScaleFactor(), executor, OBJECT_INSTANCE_ID_0));
 | 
			
		||||
        LwM2mTemperatureSensor lwM2mTemperatureSensor0 = new LwM2mTemperatureSensor(executor, OBJECT_INSTANCE_ID_0);
 | 
			
		||||
        LwM2mTemperatureSensor lwM2mTemperatureSensor12 = new LwM2mTemperatureSensor(executor, OBJECT_INSTANCE_ID_12);
 | 
			
		||||
        lwM2mTemperatureSensor12 = new LwM2mTemperatureSensor(executor, OBJECT_INSTANCE_ID_12);
 | 
			
		||||
        initializer.setInstancesForObject(TEMPERATURE_SENSOR, lwM2mTemperatureSensor0, lwM2mTemperatureSensor12);
 | 
			
		||||
 | 
			
		||||
        List<LwM2mObjectEnabler> enablers = initializer.createAll();
 | 
			
		||||
@ -315,7 +317,6 @@ public class LwM2MTestClient {
 | 
			
		||||
        clientDtlsCid = new HashMap<>();
 | 
			
		||||
        clientStates.add(ON_INIT);
 | 
			
		||||
        leshanClient = builder.build();
 | 
			
		||||
        lwM2mTemperatureSensor12.setLeshanClient(leshanClient);
 | 
			
		||||
 | 
			
		||||
        LwM2mClientObserver observer = new LwM2mClientObserver() {
 | 
			
		||||
            @Override
 | 
			
		||||
@ -452,6 +453,7 @@ public class LwM2MTestClient {
 | 
			
		||||
            if (isStartLw) {
 | 
			
		||||
                this.awaitClientAfterStartConnectLw();
 | 
			
		||||
            }
 | 
			
		||||
            lwM2mTemperatureSensor12.setLeshanClient(leshanClient);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -50,14 +50,17 @@ public class LwM2mTemperatureSensor extends BaseInstanceEnabler implements Destr
 | 
			
		||||
    private double maxMeasuredValue = currentTemp;
 | 
			
		||||
 | 
			
		||||
    private LeshanClient leshanClient;
 | 
			
		||||
    private int cntRead_5700;
 | 
			
		||||
    private int cntIdentitySystem;
 | 
			
		||||
 | 
			
		||||
    protected static final Random RANDOM = new Random();
 | 
			
		||||
    private static final List<Integer> supportedResources = Arrays.asList(5601, 5602, 5700, 5701);
 | 
			
		||||
 | 
			
		||||
    public LwM2mTemperatureSensor() {
 | 
			
		||||
    private LwM2mServer registeredServer;
 | 
			
		||||
    private ManualDataSender sender;
 | 
			
		||||
 | 
			
		||||
    private int resourceIdForSendCollected = 5700;
 | 
			
		||||
 | 
			
		||||
    public LwM2mTemperatureSensor() {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public LwM2mTemperatureSensor(ScheduledExecutorService executorService, Integer id) {
 | 
			
		||||
@ -72,26 +75,33 @@ public class LwM2mTemperatureSensor extends BaseInstanceEnabler implements Destr
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public synchronized ReadResponse read(LwM2mServer identity, int resourceId) {
 | 
			
		||||
        log.info("Read on Temperature resource /[{}]/[{}]/[{}]", getModel().id, getId(), resourceId);
 | 
			
		||||
        log.trace("Read on Temperature resource /[{}]/[{}]/[{}]", getModel().id, getId(), resourceId);
 | 
			
		||||
        if (this.registeredServer == null) {
 | 
			
		||||
            try {
 | 
			
		||||
                Lwm2mTestHelper.RESOURCE_ID_3303_12_5700_TS_0 = Instant.now().toEpochMilli();
 | 
			
		||||
                this.registeredServer = this.leshanClient.getRegisteredServers().values().iterator().next();
 | 
			
		||||
                this.sender = (ManualDataSender) this.leshanClient.getSendService().getDataSender(ManualDataSender.DEFAULT_NAME);
 | 
			
		||||
                this.sender.collectData(Arrays.asList(getPathForCollectedValue(resourceIdForSendCollected)));
 | 
			
		||||
            } catch (Exception e) {
 | 
			
		||||
                log.error("[{}] Sender for SendCollected", e.toString());
 | 
			
		||||
                e.printStackTrace();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        switch (resourceId) {
 | 
			
		||||
            case 5601:
 | 
			
		||||
                return ReadResponse.success(resourceId, getTwoDigitValue(minMeasuredValue));
 | 
			
		||||
            case 5602:
 | 
			
		||||
                return ReadResponse.success(resourceId, getTwoDigitValue(maxMeasuredValue));
 | 
			
		||||
            case 5700:
 | 
			
		||||
                if (identity == LwM2mServer.SYSTEM) { // return value for ForCollectedValue
 | 
			
		||||
                if (identity == LwM2mServer.SYSTEM) {
 | 
			
		||||
                    double val5700 = cntIdentitySystem == 0 ? RESOURCE_ID_3303_12_5700_VALUE_0 : RESOURCE_ID_3303_12_5700_VALUE_1;
 | 
			
		||||
                    cntIdentitySystem++;
 | 
			
		||||
                    return ReadResponse.success(resourceId, cntIdentitySystem == 1 ?
 | 
			
		||||
                            RESOURCE_ID_3303_12_5700_VALUE_0 : RESOURCE_ID_3303_12_5700_VALUE_1);
 | 
			
		||||
                }
 | 
			
		||||
                cntRead_5700++;
 | 
			
		||||
                if (cntRead_5700 == 1) {            // read value after start
 | 
			
		||||
                    return ReadResponse.success(resourceId, getTwoDigitValue(currentTemp));
 | 
			
		||||
                    return ReadResponse.success(resourceId, val5700);
 | 
			
		||||
                } else {
 | 
			
		||||
                    if (this.getId() == 12 && this.leshanClient != null) {
 | 
			
		||||
                    if (cntIdentitySystem == 1 && this.getId() == 12 && this.leshanClient != null) {
 | 
			
		||||
                        sendCollected();
 | 
			
		||||
                    }
 | 
			
		||||
                    return ReadResponse.success(resourceId, getTwoDigitValue(currentTemp));
 | 
			
		||||
                    return super.read(identity, resourceId);
 | 
			
		||||
                }
 | 
			
		||||
            case 5701:
 | 
			
		||||
                return ReadResponse.success(resourceId, UNIT_CELSIUS);
 | 
			
		||||
@ -163,14 +173,10 @@ public class LwM2mTemperatureSensor extends BaseInstanceEnabler implements Destr
 | 
			
		||||
 | 
			
		||||
    private void sendCollected() {
 | 
			
		||||
        try {
 | 
			
		||||
            int resourceId = 5700;
 | 
			
		||||
            LwM2mServer registeredServer = this.leshanClient.getRegisteredServers().values().iterator().next();
 | 
			
		||||
            ManualDataSender sender = this.leshanClient.getSendService().getDataSender(ManualDataSender.DEFAULT_NAME,
 | 
			
		||||
                    ManualDataSender.class);
 | 
			
		||||
            sender.collectData(Arrays.asList(getPathForCollectedValue(resourceId)));
 | 
			
		||||
            Lwm2mTestHelper.RESOURCE_ID_3303_12_5700_TS_0 = Instant.now().toEpochMilli();
 | 
			
		||||
            Thread.sleep(RESOURCE_ID_VALUE_3303_12_5700_DELTA_TS);
 | 
			
		||||
            sender.collectData(Arrays.asList(getPathForCollectedValue(resourceId)));
 | 
			
		||||
            if ((Instant.now().toEpochMilli() - Lwm2mTestHelper.RESOURCE_ID_3303_12_5700_TS_0) < RESOURCE_ID_VALUE_3303_12_5700_DELTA_TS) {
 | 
			
		||||
                Thread.sleep(RESOURCE_ID_VALUE_3303_12_5700_DELTA_TS);
 | 
			
		||||
            }
 | 
			
		||||
            sender.collectData(Arrays.asList(getPathForCollectedValue(resourceIdForSendCollected)));
 | 
			
		||||
            Lwm2mTestHelper.RESOURCE_ID_3303_12_5700_TS_1 = Instant.now().toEpochMilli();
 | 
			
		||||
            sender.sendCollectedData(registeredServer, ContentFormat.SENML_JSON, 1000, false);
 | 
			
		||||
        } catch (InterruptedException e) {
 | 
			
		||||
 | 
			
		||||
@ -71,7 +71,7 @@ import static org.thingsboard.server.transport.lwm2m.utils.LwM2MTransportUtil.fr
 | 
			
		||||
public abstract class AbstractRpcLwM2MIntegrationTest extends AbstractLwM2MIntegrationTest {
 | 
			
		||||
 | 
			
		||||
    protected final LinkParser linkParser = new DefaultLwM2mLinkParser();
 | 
			
		||||
    protected String OBSERVE_ATTRIBUTES_WITH_PARAMS_RPC;
 | 
			
		||||
    protected String CONFIG_PROFILE_WITH_PARAMS_RPC;
 | 
			
		||||
    public Set expectedObjects;
 | 
			
		||||
    public Set expectedObjectIdVers;
 | 
			
		||||
    public Set expectedInstances;
 | 
			
		||||
@ -116,10 +116,10 @@ public abstract class AbstractRpcLwM2MIntegrationTest extends AbstractLwM2MInteg
 | 
			
		||||
        if (this.getClass().getSimpleName().equals("RpcLwm2mIntegrationWriteCborTest")){
 | 
			
		||||
            supportFormatOnly_SenMLJSON_SenMLCBOR = true;
 | 
			
		||||
        }
 | 
			
		||||
        initRpc();
 | 
			
		||||
        initRpc(false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void initRpc () throws Exception {
 | 
			
		||||
    protected void initRpc(boolean isCollected) throws Exception {
 | 
			
		||||
        String endpoint = DEVICE_ENDPOINT_RPC_PREF + endpointSequence.incrementAndGet();
 | 
			
		||||
        createNewClient(SECURITY_NO_SEC, null, true, endpoint);
 | 
			
		||||
        expectedObjects = ConcurrentHashMap.newKeySet();
 | 
			
		||||
@ -157,15 +157,14 @@ public abstract class AbstractRpcLwM2MIntegrationTest extends AbstractLwM2MInteg
 | 
			
		||||
        id_3_0_9 =  fromVersionedIdToObjectId(idVer_3_0_9);
 | 
			
		||||
        idVer_19_0_0 = objectIdVer_19 + "/" + OBJECT_INSTANCE_ID_0 + "/" + RESOURCE_ID_0;
 | 
			
		||||
 | 
			
		||||
        OBSERVE_ATTRIBUTES_WITH_PARAMS_RPC =
 | 
			
		||||
        String ATTRIBUTES_TELEMETRY_WITH_PARAMS_RPC_WITH_OBSERVE =
 | 
			
		||||
                "    {\n" +
 | 
			
		||||
                        "    \"keyName\": {\n" +
 | 
			
		||||
                        "      \"" + idVer_3_0_9 + "\": \"" + RESOURCE_ID_NAME_3_9 + "\",\n" +
 | 
			
		||||
                        "      \"" + objectIdVer_3 + "/" + OBJECT_INSTANCE_ID_0 + "/" + RESOURCE_ID_14 + "\": \"" + RESOURCE_ID_NAME_3_14 + "\",\n" +
 | 
			
		||||
                        "      \"" + idVer_19_0_0 + "\": \"" + RESOURCE_ID_NAME_19_0_0 + "\",\n" +
 | 
			
		||||
                        "      \"" + objectIdVer_19 + "/" + OBJECT_INSTANCE_ID_1 + "/" + RESOURCE_ID_0 + "\": \"" + RESOURCE_ID_NAME_19_1_0 + "\",\n" +
 | 
			
		||||
                        "      \"" + objectIdVer_19 + "/" + OBJECT_INSTANCE_ID_0 + "/" + RESOURCE_ID_2 + "\": \"" + RESOURCE_ID_NAME_19_0_2 + "\",\n" +
 | 
			
		||||
                        "      \"" + objectIdVer_3303 + "/" + OBJECT_INSTANCE_ID_12 + "/" + RESOURCE_ID_5700 + "\": \"" + RESOURCE_ID_NAME_3303_12_5700 + "\"\n" +
 | 
			
		||||
                        "      \"" + objectIdVer_19 + "/" + OBJECT_INSTANCE_ID_0 + "/" + RESOURCE_ID_2 + "\": \"" + RESOURCE_ID_NAME_19_0_2 + "\"\n" +
 | 
			
		||||
                        "    },\n" +
 | 
			
		||||
                        "    \"observe\": [\n" +
 | 
			
		||||
                        "      \"" + idVer_3_0_9 + "\",\n" +
 | 
			
		||||
@ -180,13 +179,29 @@ public abstract class AbstractRpcLwM2MIntegrationTest extends AbstractLwM2MInteg
 | 
			
		||||
                        "    \"telemetry\": [\n" +
 | 
			
		||||
                        "      \"" + idVer_3_0_9 + "\",\n" +
 | 
			
		||||
                        "      \"" + idVer_19_0_0 + "\",\n" +
 | 
			
		||||
                        "      \"" + objectIdVer_19 + "/" + OBJECT_INSTANCE_ID_1 + "/" + RESOURCE_ID_0 + "\",\n" +
 | 
			
		||||
                        "      \"" + objectIdVer_3303 + "/" + OBJECT_INSTANCE_ID_12 + "/" + RESOURCE_ID_5700 + "\"\n" +
 | 
			
		||||
                        "      \"" + objectIdVer_19 + "/" + OBJECT_INSTANCE_ID_1 + "/" + RESOURCE_ID_0 + "\"\n" +
 | 
			
		||||
                        "    ],\n" +
 | 
			
		||||
                        "    \"attributeLwm2m\": {}\n" +
 | 
			
		||||
                        "  }";
 | 
			
		||||
 | 
			
		||||
        Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITH_PARAMS_RPC, getBootstrapServerCredentialsNoSec(NONE));
 | 
			
		||||
        String TELEMETRY_WITH_PARAMS_RPC_WITHOUT_OBSERVE =
 | 
			
		||||
                "    {\n" +
 | 
			
		||||
                        "    \"keyName\": {\n" +
 | 
			
		||||
                        "      \"" + objectIdVer_3303 + "/" + OBJECT_INSTANCE_ID_12 + "/" + RESOURCE_ID_5700 + "\": \"" + RESOURCE_ID_NAME_3303_12_5700 + "\"\n" +
 | 
			
		||||
                        "    },\n" +
 | 
			
		||||
                        "    \"observe\": [\n" +
 | 
			
		||||
                        "    ],\n" +
 | 
			
		||||
                        "    \"attribute\": [\n" +
 | 
			
		||||
                        "    ],\n" +
 | 
			
		||||
                        "    \"telemetry\": [\n" +
 | 
			
		||||
                        "      \"" + objectIdVer_3303 + "/" + OBJECT_INSTANCE_ID_12 + "/" + RESOURCE_ID_5700 + "\"\n" +
 | 
			
		||||
                        "    ],\n" +
 | 
			
		||||
                        "    \"attributeLwm2m\": {}\n" +
 | 
			
		||||
                        "  }" ;
 | 
			
		||||
 | 
			
		||||
        CONFIG_PROFILE_WITH_PARAMS_RPC = isCollected ? TELEMETRY_WITH_PARAMS_RPC_WITHOUT_OBSERVE : ATTRIBUTES_TELEMETRY_WITH_PARAMS_RPC_WITH_OBSERVE;
 | 
			
		||||
 | 
			
		||||
        Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration(CONFIG_PROFILE_WITH_PARAMS_RPC, getBootstrapServerCredentialsNoSec(NONE));
 | 
			
		||||
        createDeviceProfile(transportConfiguration);
 | 
			
		||||
 | 
			
		||||
        LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsNoSec(createNoSecClientCredentials(endpoint));
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,103 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Copyright © 2016-2024 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.databind.JsonNode;
 | 
			
		||||
import com.fasterxml.jackson.databind.node.ArrayNode;
 | 
			
		||||
import com.fasterxml.jackson.databind.node.ObjectNode;
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import org.junit.Before;
 | 
			
		||||
import org.junit.Test;
 | 
			
		||||
import org.thingsboard.server.transport.lwm2m.rpc.AbstractRpcLwM2MIntegrationTest;
 | 
			
		||||
import java.util.concurrent.atomic.AtomicReference;
 | 
			
		||||
import static java.util.concurrent.TimeUnit.SECONDS;
 | 
			
		||||
import static org.awaitility.Awaitility.await;
 | 
			
		||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
 | 
			
		||||
import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.OBJECT_INSTANCE_ID_12;
 | 
			
		||||
import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.RESOURCE_ID_3303_12_5700_TS_0;
 | 
			
		||||
import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.RESOURCE_ID_3303_12_5700_TS_1;
 | 
			
		||||
import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.RESOURCE_ID_3303_12_5700_VALUE_0;
 | 
			
		||||
import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.RESOURCE_ID_3303_12_5700_VALUE_1;
 | 
			
		||||
import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.RESOURCE_ID_NAME_3303_12_5700;
 | 
			
		||||
import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.RESOURCE_ID_VALUE_3303_12_5700_DELTA_TS;
 | 
			
		||||
 | 
			
		||||
@Slf4j
 | 
			
		||||
public class RpcLwm2mIntegrationReadCollectedValueTest extends AbstractRpcLwM2MIntegrationTest {
 | 
			
		||||
 | 
			
		||||
    @Before
 | 
			
		||||
    public void startInitRPC() throws Exception {
 | 
			
		||||
        initRpc(true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Read {"id":"/3303/12/5700"}
 | 
			
		||||
     * Trigger a Send operation from the client with multiple values for the same resource as a payload
 | 
			
		||||
     * acked "[{"bn":"/3303/12/5700","bt":1724".. 116 bytes]
 | 
			
		||||
     * 2 values for the resource /3303/12/5700 should be stored with:
 | 
			
		||||
     * - timestamps1 =  Instance.now() + RESOURCE_ID_VALUE_3303_12_5700_1
 | 
			
		||||
     * - timestamps2 =  (timestamps1 + 3 sec) + RESOURCE_ID_VALUE_3303_12_5700_2
 | 
			
		||||
     * @throws Exception
 | 
			
		||||
     */
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testReadSingleResource_sendFromClient_CollectedValue() throws Exception {
 | 
			
		||||
        // init test
 | 
			
		||||
        int cntValues = 2;
 | 
			
		||||
        int resourceId = 5700;
 | 
			
		||||
        String expectedIdVer = objectIdVer_3303 + "/" + OBJECT_INSTANCE_ID_12 + "/" + resourceId;
 | 
			
		||||
        sendRPCById(expectedIdVer);
 | 
			
		||||
 | 
			
		||||
        // verify time start/end send CollectedValue;
 | 
			
		||||
        await().atMost(40, SECONDS).until(() -> RESOURCE_ID_3303_12_5700_TS_0 > 0
 | 
			
		||||
                                                    && RESOURCE_ID_3303_12_5700_TS_1 > 0);
 | 
			
		||||
 | 
			
		||||
        // verify result read: verify count value: 1-2: send CollectedValue;
 | 
			
		||||
        AtomicReference<ObjectNode> actualValues = new AtomicReference<>();
 | 
			
		||||
        await().atMost(40, SECONDS).until(() -> {
 | 
			
		||||
            actualValues.set(doGetAsync(
 | 
			
		||||
                    "/api/plugins/telemetry/DEVICE/" + deviceId + "/values/timeseries?keys="
 | 
			
		||||
                            + RESOURCE_ID_NAME_3303_12_5700
 | 
			
		||||
                            + "&startTs=" + (RESOURCE_ID_3303_12_5700_TS_0 - RESOURCE_ID_VALUE_3303_12_5700_DELTA_TS)
 | 
			
		||||
                            + "&endTs=" + (RESOURCE_ID_3303_12_5700_TS_1 + RESOURCE_ID_VALUE_3303_12_5700_DELTA_TS)
 | 
			
		||||
                            + "&interval=0&limit=100&useStrictDataTypes=false",
 | 
			
		||||
                    ObjectNode.class));
 | 
			
		||||
            return actualValues.get() != null && actualValues.get().size() > 0
 | 
			
		||||
                    && actualValues.get().get(RESOURCE_ID_NAME_3303_12_5700).size() >= cntValues && verifyTs(actualValues);
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private boolean verifyTs(AtomicReference<ObjectNode> actualValues) {
 | 
			
		||||
        String expectedVal_0 = String.valueOf(RESOURCE_ID_3303_12_5700_VALUE_0);
 | 
			
		||||
        String expectedVal_1 = String.valueOf(RESOURCE_ID_3303_12_5700_VALUE_1);
 | 
			
		||||
        ArrayNode actual = (ArrayNode) actualValues.get().get(RESOURCE_ID_NAME_3303_12_5700);
 | 
			
		||||
        long actualTS0 = 0;
 | 
			
		||||
        long actualTS1 = 0;
 | 
			
		||||
        for (JsonNode tsNode : actual) {
 | 
			
		||||
            if (tsNode.get("value").asText().equals(expectedVal_0)) {
 | 
			
		||||
                actualTS0 = tsNode.get("ts").asLong();
 | 
			
		||||
            } else if (tsNode.get("value").asText().equals(expectedVal_1)) {
 | 
			
		||||
                actualTS1 = tsNode.get("ts").asLong();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return actualTS0 >= RESOURCE_ID_3303_12_5700_TS_0
 | 
			
		||||
                && actualTS1 <= RESOURCE_ID_3303_12_5700_TS_1
 | 
			
		||||
                && (actualTS1 - actualTS0) >= RESOURCE_ID_VALUE_3303_12_5700_DELTA_TS;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private String sendRPCById(String path) throws Exception {
 | 
			
		||||
        String setRpcRequest = "{\"method\": \"Read\", \"params\": {\"id\": \"" + path + "\"}}";
 | 
			
		||||
        return doPostAsync("/api/plugins/rpc/twoway/" + deviceId, setRpcRequest, String.class, status().isOk());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -15,23 +15,15 @@
 | 
			
		||||
 */
 | 
			
		||||
package org.thingsboard.server.transport.lwm2m.rpc.sql;
 | 
			
		||||
 | 
			
		||||
import com.fasterxml.jackson.databind.JsonNode;
 | 
			
		||||
import com.fasterxml.jackson.databind.node.ArrayNode;
 | 
			
		||||
import com.fasterxml.jackson.databind.node.ObjectNode;
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import org.apache.commons.collections4.map.HashedMap;
 | 
			
		||||
import org.eclipse.leshan.core.ResponseCode;
 | 
			
		||||
import org.eclipse.leshan.core.node.LwM2mPath;
 | 
			
		||||
import org.junit.Before;
 | 
			
		||||
import org.junit.Test;
 | 
			
		||||
import org.thingsboard.common.util.JacksonUtil;
 | 
			
		||||
import org.thingsboard.server.transport.lwm2m.rpc.AbstractRpcLwM2MIntegrationTest;
 | 
			
		||||
 | 
			
		||||
import java.time.Instant;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
import java.util.concurrent.atomic.AtomicReference;
 | 
			
		||||
 | 
			
		||||
import static java.util.concurrent.TimeUnit.SECONDS;
 | 
			
		||||
import static org.awaitility.Awaitility.await;
 | 
			
		||||
import static org.eclipse.leshan.core.LwM2mId.SERVER;
 | 
			
		||||
import static org.junit.Assert.assertEquals;
 | 
			
		||||
import static org.junit.Assert.assertTrue;
 | 
			
		||||
@ -39,24 +31,17 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
 | 
			
		||||
import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.BINARY_APP_DATA_CONTAINER;
 | 
			
		||||
import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.OBJECT_INSTANCE_ID_0;
 | 
			
		||||
import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.OBJECT_INSTANCE_ID_1;
 | 
			
		||||
import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.OBJECT_INSTANCE_ID_12;
 | 
			
		||||
import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.RESOURCE_ID_0;
 | 
			
		||||
import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.RESOURCE_ID_1;
 | 
			
		||||
import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.RESOURCE_ID_11;
 | 
			
		||||
import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.RESOURCE_ID_14;
 | 
			
		||||
import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.RESOURCE_ID_2;
 | 
			
		||||
import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.RESOURCE_ID_3303_12_5700_TS_0;
 | 
			
		||||
import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.RESOURCE_ID_3303_12_5700_TS_1;
 | 
			
		||||
import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.RESOURCE_ID_9;
 | 
			
		||||
import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.RESOURCE_ID_NAME_19_0_0;
 | 
			
		||||
import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.RESOURCE_ID_NAME_19_0_3;
 | 
			
		||||
import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.RESOURCE_ID_NAME_19_1_0;
 | 
			
		||||
import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.RESOURCE_ID_NAME_3303_12_5700;
 | 
			
		||||
import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.RESOURCE_ID_NAME_3_14;
 | 
			
		||||
import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.RESOURCE_ID_NAME_3_9;
 | 
			
		||||
import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.RESOURCE_ID_3303_12_5700_VALUE_0;
 | 
			
		||||
import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.RESOURCE_ID_3303_12_5700_VALUE_1;
 | 
			
		||||
import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.RESOURCE_ID_VALUE_3303_12_5700_DELTA_TS;
 | 
			
		||||
 | 
			
		||||
@Slf4j
 | 
			
		||||
public class RpcLwm2mIntegrationReadTest extends AbstractRpcLwM2MIntegrationTest {
 | 
			
		||||
@ -228,59 +213,6 @@ public class RpcLwm2mIntegrationReadTest extends AbstractRpcLwM2MIntegrationTest
 | 
			
		||||
        assertTrue(actualValues.contains(expected19_1_0));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Read {"id":"/3303/12/5700"}
 | 
			
		||||
     * Trigger a Send operation from the client with multiple values for the same resource as a payload
 | 
			
		||||
     * acked "[{"bn":"/3303/12/5700","bt":1724".. 116 bytes]
 | 
			
		||||
     * 2 values for the resource /3303/12/5700 should be stored with:
 | 
			
		||||
     * - timestamps1 =  Instance.now() + RESOURCE_ID_VALUE_3303_12_5700_1
 | 
			
		||||
     * - timestamps2 =  (timestamps1 + 3 sec) + RESOURCE_ID_VALUE_3303_12_5700_2
 | 
			
		||||
     * @throws Exception
 | 
			
		||||
     */
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testReadSingleResource_sendFromClient_CollectedValue() throws Exception {
 | 
			
		||||
        // init test
 | 
			
		||||
        long startTs = Instant.now().toEpochMilli();
 | 
			
		||||
        int cntValues = 4;
 | 
			
		||||
        int resourceId = 5700;
 | 
			
		||||
        String expectedIdVer = objectIdVer_3303 + "/" + OBJECT_INSTANCE_ID_12 + "/" + resourceId;
 | 
			
		||||
        sendRPCById(expectedIdVer);
 | 
			
		||||
        // verify result read: verify count value: 1-2: send CollectedValue; 3 - response for read;
 | 
			
		||||
        long endTs = Instant.now().toEpochMilli() + RESOURCE_ID_VALUE_3303_12_5700_DELTA_TS * 4;
 | 
			
		||||
        String expectedVal_1 = String.valueOf(RESOURCE_ID_3303_12_5700_VALUE_0);
 | 
			
		||||
        String expectedVal_2 = String.valueOf(RESOURCE_ID_3303_12_5700_VALUE_1);
 | 
			
		||||
        AtomicReference<ObjectNode> actualValues = new AtomicReference<>();
 | 
			
		||||
        await().atMost(40, SECONDS).until(() -> {
 | 
			
		||||
            actualValues.set(doGetAsync(
 | 
			
		||||
                    "/api/plugins/telemetry/DEVICE/" + deviceId + "/values/timeseries?keys="
 | 
			
		||||
                            + RESOURCE_ID_NAME_3303_12_5700
 | 
			
		||||
                            + "&startTs=" + startTs
 | 
			
		||||
                            + "&endTs=" + endTs
 | 
			
		||||
                            + "&interval=0&limit=100&useStrictDataTypes=false",
 | 
			
		||||
                    ObjectNode.class));
 | 
			
		||||
            // verify cntValues
 | 
			
		||||
            return actualValues.get() != null && actualValues.get().get(RESOURCE_ID_NAME_3303_12_5700).size() == cntValues;
 | 
			
		||||
        });
 | 
			
		||||
        // verify ts
 | 
			
		||||
        ArrayNode actual = (ArrayNode) actualValues.get().get(RESOURCE_ID_NAME_3303_12_5700);
 | 
			
		||||
        Map<String, Long> keyTsMaps = new HashedMap();
 | 
			
		||||
        for (JsonNode tsNode: actual) {
 | 
			
		||||
            if (tsNode.get("value").asText().equals(expectedVal_1) || tsNode.get("value").asText().equals(expectedVal_2)) {
 | 
			
		||||
                keyTsMaps.put(tsNode.get("value").asText(), tsNode.get("ts").asLong());
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        assertTrue(keyTsMaps.size() == 2);
 | 
			
		||||
        long actualTS0 = keyTsMaps.get(expectedVal_1).longValue();
 | 
			
		||||
        long actualTS1 = keyTsMaps.get(expectedVal_2).longValue();
 | 
			
		||||
        assertTrue(actualTS0 > 0);
 | 
			
		||||
        assertTrue(actualTS1 > 0);
 | 
			
		||||
        assertTrue(actualTS1 > actualTS0);
 | 
			
		||||
        assertTrue((actualTS1 - actualTS0) >= RESOURCE_ID_VALUE_3303_12_5700_DELTA_TS);
 | 
			
		||||
        assertTrue(actualTS0 <= RESOURCE_ID_3303_12_5700_TS_0);
 | 
			
		||||
        assertTrue(actualTS1 <= RESOURCE_ID_3303_12_5700_TS_1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * ReadComposite {"keys":["batteryLevel", "UtfOffset", "dataDescription"]}
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user