committed by
Andrew Shvayka
15 changed files with 391 additions and 24 deletions
@ -0,0 +1,205 @@ |
|||
/** |
|||
* 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; |
|||
|
|||
import org.eclipse.californium.core.network.config.NetworkConfig; |
|||
import org.eclipse.leshan.client.object.Security; |
|||
import org.jetbrains.annotations.NotNull; |
|||
import org.junit.Assert; |
|||
import org.junit.Test; |
|||
import org.thingsboard.common.util.JacksonUtil; |
|||
import org.thingsboard.server.common.data.Device; |
|||
import org.thingsboard.server.common.data.query.EntityData; |
|||
import org.thingsboard.server.common.data.query.EntityDataPageLink; |
|||
import org.thingsboard.server.common.data.query.EntityDataQuery; |
|||
import org.thingsboard.server.common.data.query.EntityKey; |
|||
import org.thingsboard.server.common.data.query.EntityKeyType; |
|||
import org.thingsboard.server.common.data.query.SingleEntityFilter; |
|||
import org.thingsboard.server.common.data.security.DeviceCredentials; |
|||
import org.thingsboard.server.common.data.security.DeviceCredentialsType; |
|||
import org.thingsboard.server.common.transport.util.SslUtil; |
|||
import org.thingsboard.server.service.telemetry.cmd.TelemetryPluginCmdsWrapper; |
|||
import org.thingsboard.server.service.telemetry.cmd.v2.EntityDataCmd; |
|||
import org.thingsboard.server.service.telemetry.cmd.v2.EntityDataUpdate; |
|||
import org.thingsboard.server.service.telemetry.cmd.v2.LatestValueCmd; |
|||
import org.thingsboard.server.transport.lwm2m.client.LwM2MTestClient; |
|||
import org.thingsboard.server.transport.lwm2m.secure.credentials.LwM2MCredentials; |
|||
import org.thingsboard.server.transport.lwm2m.secure.credentials.X509ClientCredentialsConfig; |
|||
|
|||
import java.util.Collections; |
|||
import java.util.List; |
|||
|
|||
import static org.eclipse.leshan.client.object.Security.x509; |
|||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; |
|||
|
|||
public class X509LwM2MIntegrationTest extends AbstractLwM2MIntegrationTest { |
|||
|
|||
protected final String TRANSPORT_CONFIGURATION = "{\n" + |
|||
" \"type\": \"LWM2M\",\n" + |
|||
" \"observeAttr\": {\n" + |
|||
" \"keyName\": {\n" + |
|||
" \"/3_1.0/0/9\": \"batteryLevel\"\n" + |
|||
" },\n" + |
|||
" \"observe\": [],\n" + |
|||
" \"attribute\": [\n" + |
|||
" ],\n" + |
|||
" \"telemetry\": [\n" + |
|||
" \"/3_1.0/0/9\"\n" + |
|||
" ],\n" + |
|||
" \"attributeLwm2m\": {}\n" + |
|||
" },\n" + |
|||
" \"bootstrap\": {\n" + |
|||
" \"servers\": {\n" + |
|||
" \"binding\": \"UQ\",\n" + |
|||
" \"shortId\": 123,\n" + |
|||
" \"lifetime\": 300,\n" + |
|||
" \"notifIfDisabled\": true,\n" + |
|||
" \"defaultMinPeriod\": 1\n" + |
|||
" },\n" + |
|||
" \"lwm2mServer\": {\n" + |
|||
" \"host\": \"localhost\",\n" + |
|||
" \"port\": 5686,\n" + |
|||
" \"serverId\": 123,\n" + |
|||
" \"serverPublicKey\": \"\",\n" + |
|||
" \"bootstrapServerIs\": false,\n" + |
|||
" \"clientHoldOffTime\": 1,\n" + |
|||
" \"bootstrapServerAccountTimeout\": 0\n" + |
|||
" },\n" + |
|||
" \"bootstrapServer\": {\n" + |
|||
" \"host\": \"localhost\",\n" + |
|||
" \"port\": 5687,\n" + |
|||
" \"serverId\": 111,\n" + |
|||
" \"securityMode\": \"NO_SEC\",\n" + |
|||
" \"serverPublicKey\": \"\",\n" + |
|||
" \"bootstrapServerIs\": true,\n" + |
|||
" \"clientHoldOffTime\": 1,\n" + |
|||
" \"bootstrapServerAccountTimeout\": 0\n" + |
|||
" }\n" + |
|||
" },\n" + |
|||
" \"clientLwM2mSettings\": {\n" + |
|||
" \"clientOnlyObserveAfterConnect\": 1\n" + |
|||
" }\n" + |
|||
"}"; |
|||
|
|||
|
|||
private final int port = 5686; |
|||
private final NetworkConfig coapConfig = new NetworkConfig().setString("COAP_SECURE_PORT", Integer.toString(port)); |
|||
private final String endpoint = "deviceAEndpoint"; |
|||
private final String serverUri = "coaps://localhost:" + port; |
|||
|
|||
@NotNull |
|||
private Device createDevice(String credentialsId, X509ClientCredentialsConfig credentialsConfig) throws Exception { |
|||
Device device = new Device(); |
|||
device.setName("Device A"); |
|||
device.setDeviceProfileId(deviceProfile.getId()); |
|||
device.setTenantId(tenantId); |
|||
device = doPost("/api/device", device, Device.class); |
|||
Assert.assertNotNull(device); |
|||
|
|||
DeviceCredentials deviceCredentials = |
|||
doGet("/api/device/" + device.getId().getId().toString() + "/credentials", DeviceCredentials.class); |
|||
Assert.assertEquals(device.getId(), deviceCredentials.getDeviceId()); |
|||
deviceCredentials.setCredentialsType(DeviceCredentialsType.LWM2M_CREDENTIALS); |
|||
|
|||
deviceCredentials.setCredentialsId(credentialsId); |
|||
|
|||
LwM2MCredentials X509Credentials = new LwM2MCredentials(); |
|||
|
|||
X509Credentials.setClient(credentialsConfig); |
|||
|
|||
deviceCredentials.setCredentialsValue(JacksonUtil.toString(X509Credentials)); |
|||
doPost("/api/device/credentials", deviceCredentials).andExpect(status().isOk()); |
|||
return device; |
|||
} |
|||
|
|||
@Test |
|||
public void testConnectAndObserveTelemetry() throws Exception { |
|||
createDeviceProfile(TRANSPORT_CONFIGURATION); |
|||
|
|||
Device device = createDevice(endpoint, new X509ClientCredentialsConfig(null, null)); |
|||
|
|||
SingleEntityFilter sef = new SingleEntityFilter(); |
|||
sef.setSingleEntity(device.getId()); |
|||
LatestValueCmd latestCmd = new LatestValueCmd(); |
|||
latestCmd.setKeys(Collections.singletonList(new EntityKey(EntityKeyType.TIME_SERIES, "batteryLevel"))); |
|||
EntityDataQuery edq = new EntityDataQuery(sef, new EntityDataPageLink(1, 0, null, null), |
|||
Collections.emptyList(), Collections.emptyList(), Collections.emptyList()); |
|||
|
|||
EntityDataCmd cmd = new EntityDataCmd(1, edq, null, latestCmd, null); |
|||
TelemetryPluginCmdsWrapper wrapper = new TelemetryPluginCmdsWrapper(); |
|||
wrapper.setEntityDataCmds(Collections.singletonList(cmd)); |
|||
|
|||
wsClient.send(mapper.writeValueAsString(wrapper)); |
|||
wsClient.waitForReply(); |
|||
|
|||
wsClient.registerWaitForUpdate(); |
|||
LwM2MTestClient client = new LwM2MTestClient(executor, endpoint); |
|||
Security security = x509(serverUri, 123, clientX509Cert.getEncoded(), clientPrivateKeyFromCert.getEncoded(), serverX509Cert.getEncoded()); |
|||
client.init(security, coapConfig); |
|||
String msg = wsClient.waitForUpdate(); |
|||
|
|||
EntityDataUpdate update = mapper.readValue(msg, EntityDataUpdate.class); |
|||
Assert.assertEquals(1, update.getCmdId()); |
|||
List<EntityData> eData = update.getUpdate(); |
|||
Assert.assertNotNull(eData); |
|||
Assert.assertEquals(1, eData.size()); |
|||
Assert.assertEquals(device.getId(), eData.get(0).getEntityId()); |
|||
Assert.assertNotNull(eData.get(0).getLatest().get(EntityKeyType.TIME_SERIES)); |
|||
var tsValue = eData.get(0).getLatest().get(EntityKeyType.TIME_SERIES).get("batteryLevel"); |
|||
Assert.assertEquals(42, Long.parseLong(tsValue.getValue())); |
|||
client.destroy(); |
|||
} |
|||
|
|||
@Test |
|||
public void testConnectWithCertAndObserveTelemetry() throws Exception { |
|||
createDeviceProfile(TRANSPORT_CONFIGURATION); |
|||
Device device = createDevice(null, new X509ClientCredentialsConfig(SslUtil.getCertificateString(clientX509CertNotTrusted), endpoint)); |
|||
|
|||
SingleEntityFilter sef = new SingleEntityFilter(); |
|||
sef.setSingleEntity(device.getId()); |
|||
LatestValueCmd latestCmd = new LatestValueCmd(); |
|||
latestCmd.setKeys(Collections.singletonList(new EntityKey(EntityKeyType.TIME_SERIES, "batteryLevel"))); |
|||
EntityDataQuery edq = new EntityDataQuery(sef, new EntityDataPageLink(1, 0, null, null), |
|||
Collections.emptyList(), Collections.emptyList(), Collections.emptyList()); |
|||
|
|||
EntityDataCmd cmd = new EntityDataCmd(1, edq, null, latestCmd, null); |
|||
TelemetryPluginCmdsWrapper wrapper = new TelemetryPluginCmdsWrapper(); |
|||
wrapper.setEntityDataCmds(Collections.singletonList(cmd)); |
|||
|
|||
wsClient.send(mapper.writeValueAsString(wrapper)); |
|||
wsClient.waitForReply(); |
|||
|
|||
wsClient.registerWaitForUpdate(); |
|||
LwM2MTestClient client = new LwM2MTestClient(executor, endpoint); |
|||
|
|||
Security security = x509(serverUri, 123, clientX509CertNotTrusted.getEncoded(), clientPrivateKeyFromCert.getEncoded(), serverX509Cert.getEncoded()); |
|||
|
|||
client.init(security, coapConfig); |
|||
String msg = wsClient.waitForUpdate(); |
|||
|
|||
EntityDataUpdate update = mapper.readValue(msg, EntityDataUpdate.class); |
|||
Assert.assertEquals(1, update.getCmdId()); |
|||
List<EntityData> eData = update.getUpdate(); |
|||
Assert.assertNotNull(eData); |
|||
Assert.assertEquals(1, eData.size()); |
|||
Assert.assertEquals(device.getId(), eData.get(0).getEntityId()); |
|||
Assert.assertNotNull(eData.get(0).getLatest().get(EntityKeyType.TIME_SERIES)); |
|||
var tsValue = eData.get(0).getLatest().get(EntityKeyType.TIME_SERIES).get("batteryLevel"); |
|||
Assert.assertEquals(42, Long.parseLong(tsValue.getValue())); |
|||
client.destroy(); |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,2 @@ |
|||
transport.lwm2m.security.key_store=lwm2m/credentials/serverKeyStore.jks |
|||
transport.lwm2m.security.key_store_password=server |
|||
Binary file not shown.
Binary file not shown.
Loading…
Reference in new issue