Browse Source
* init CoapDeviceProfile & added ui components * added transport payload type configuration for default coap device type * added AbstractCoapTransportResource & updated efento resource * fixed coap device profile save & update * fixed Attribute Updates notifications * revert CoapOkCallback onSuccess changes * updated provision request to handle proto payload type * fix license * updated Rpc subscribe/unsubscribe action * add more device emulator clients * added fix for Coap Transport: ability to handle requests with oneElementUriPaths and MultiElementUriPaths * fix TbCoapServer implementation * changed response type to CREATED in POST requests * improved implementation * fix typos * minor bug-fixes & improvements * fix TbCoapServerMessageDeliverer class * improved relay sensor implementation * added tests for CoAP transport\ * fix typo * removed nosql tests * fix coap endpoint creation & improved getAttributes tests * transport tests refactoringpull/4257/head
committed by
GitHub
141 changed files with 5305 additions and 827 deletions
@ -1,24 +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.mqtt.attributes.request.nosql; |
|||
|
|||
import org.thingsboard.server.dao.service.DaoNoSqlTest; |
|||
import org.thingsboard.server.mqtt.attributes.request.AbstractMqttAttributesRequestIntegrationTest; |
|||
|
|||
|
|||
@DaoNoSqlTest |
|||
public class MqttAttributesRequestNoSqlIntegrationTest extends AbstractMqttAttributesRequestIntegrationTest { |
|||
} |
|||
@ -1,26 +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.mqtt.rpc.nosql; |
|||
|
|||
import org.thingsboard.server.dao.service.DaoNoSqlTest; |
|||
import org.thingsboard.server.mqtt.rpc.AbstractMqttServerSideRpcDefaultIntegrationTest; |
|||
|
|||
/** |
|||
* Created by Valerii Sosliuk on 8/22/2017. |
|||
*/ |
|||
@DaoNoSqlTest |
|||
public class MqttServerSideRpcNoSqlIntegrationTest extends AbstractMqttServerSideRpcDefaultIntegrationTest { |
|||
} |
|||
@ -1,23 +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.mqtt.telemetry.attributes.nosql; |
|||
|
|||
import org.thingsboard.server.dao.service.DaoNoSqlTest; |
|||
import org.thingsboard.server.mqtt.telemetry.attributes.AbstractMqttAttributesIntegrationTest; |
|||
|
|||
@DaoNoSqlTest |
|||
public class MqttAttributesNoSqlIntegrationTest extends AbstractMqttAttributesIntegrationTest { |
|||
} |
|||
@ -1,23 +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.mqtt.telemetry.attributes.nosql; |
|||
|
|||
import org.thingsboard.server.dao.service.DaoNoSqlTest; |
|||
import org.thingsboard.server.mqtt.telemetry.attributes.AbstractMqttAttributesProtoIntegrationTest; |
|||
|
|||
@DaoNoSqlTest |
|||
public class MqttAttributesNoSqlProtoIntegrationTest extends AbstractMqttAttributesProtoIntegrationTest { |
|||
} |
|||
@ -0,0 +1,191 @@ |
|||
/** |
|||
* 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; |
|||
|
|||
import com.fasterxml.jackson.databind.node.ObjectNode; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.eclipse.paho.client.mqttv3.MqttAsyncClient; |
|||
import org.eclipse.paho.client.mqttv3.MqttConnectOptions; |
|||
import org.eclipse.paho.client.mqttv3.MqttException; |
|||
import org.eclipse.paho.client.mqttv3.MqttMessage; |
|||
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence; |
|||
import org.junit.Assert; |
|||
import org.springframework.util.StringUtils; |
|||
import org.thingsboard.server.common.data.Device; |
|||
import org.thingsboard.server.common.data.DeviceProfile; |
|||
import org.thingsboard.server.common.data.DeviceProfileProvisionType; |
|||
import org.thingsboard.server.common.data.DeviceProfileType; |
|||
import org.thingsboard.server.common.data.DeviceTransportType; |
|||
import org.thingsboard.server.common.data.Tenant; |
|||
import org.thingsboard.server.common.data.TransportPayloadType; |
|||
import org.thingsboard.server.common.data.User; |
|||
import org.thingsboard.server.common.data.device.profile.AllowCreateNewDevicesDeviceProfileProvisionConfiguration; |
|||
import org.thingsboard.server.common.data.device.profile.CheckPreProvisionedDevicesDeviceProfileProvisionConfiguration; |
|||
import org.thingsboard.server.common.data.device.profile.DefaultDeviceProfileConfiguration; |
|||
import org.thingsboard.server.common.data.device.profile.DeviceProfileData; |
|||
import org.thingsboard.server.common.data.device.profile.DeviceProfileProvisionConfiguration; |
|||
import org.thingsboard.server.common.data.device.profile.DisabledDeviceProfileProvisionConfiguration; |
|||
import org.thingsboard.server.common.data.device.profile.JsonTransportPayloadConfiguration; |
|||
import org.thingsboard.server.common.data.device.profile.MqttDeviceProfileTransportConfiguration; |
|||
import org.thingsboard.server.common.data.device.profile.ProtoTransportPayloadConfiguration; |
|||
import org.thingsboard.server.common.data.device.profile.TransportPayloadTypeConfiguration; |
|||
import org.thingsboard.server.common.data.security.Authority; |
|||
import org.thingsboard.server.common.data.security.DeviceCredentials; |
|||
import org.thingsboard.server.controller.AbstractControllerTest; |
|||
import org.thingsboard.server.gen.transport.TransportProtos; |
|||
|
|||
import java.util.ArrayList; |
|||
import java.util.List; |
|||
import java.util.concurrent.atomic.AtomicInteger; |
|||
|
|||
import static org.junit.Assert.assertEquals; |
|||
import static org.junit.Assert.assertNotNull; |
|||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; |
|||
|
|||
@Slf4j |
|||
public abstract class AbstractTransportIntegrationTest extends AbstractControllerTest { |
|||
|
|||
protected static final String MQTT_URL = "tcp://localhost:1883"; |
|||
protected static final String COAP_BASE_URL = "coap://localhost:5683/api/v1/"; |
|||
|
|||
protected static final AtomicInteger atomicInteger = new AtomicInteger(2); |
|||
|
|||
protected static final String DEVICE_TELEMETRY_PROTO_SCHEMA = "syntax =\"proto3\";\n" + |
|||
"\n" + |
|||
"package test;\n" + |
|||
"\n" + |
|||
"message PostTelemetry {\n" + |
|||
" string key1 = 1;\n" + |
|||
" bool key2 = 2;\n" + |
|||
" double key3 = 3;\n" + |
|||
" int32 key4 = 4;\n" + |
|||
" JsonObject key5 = 5;\n" + |
|||
"\n" + |
|||
" message JsonObject {\n" + |
|||
" int32 someNumber = 6;\n" + |
|||
" repeated int32 someArray = 7;\n" + |
|||
" NestedJsonObject someNestedObject = 8;\n" + |
|||
" message NestedJsonObject {\n" + |
|||
" string key = 9;\n" + |
|||
" }\n" + |
|||
" }\n" + |
|||
"}"; |
|||
|
|||
protected static final String DEVICE_ATTRIBUTES_PROTO_SCHEMA = "syntax =\"proto3\";\n" + |
|||
"\n" + |
|||
"package test;\n" + |
|||
"\n" + |
|||
"message PostAttributes {\n" + |
|||
" string key1 = 1;\n" + |
|||
" bool key2 = 2;\n" + |
|||
" double key3 = 3;\n" + |
|||
" int32 key4 = 4;\n" + |
|||
" JsonObject key5 = 5;\n" + |
|||
"\n" + |
|||
" message JsonObject {\n" + |
|||
" int32 someNumber = 6;\n" + |
|||
" repeated int32 someArray = 7;\n" + |
|||
" NestedJsonObject someNestedObject = 8;\n" + |
|||
" message NestedJsonObject {\n" + |
|||
" string key = 9;\n" + |
|||
" }\n" + |
|||
" }\n" + |
|||
"}"; |
|||
|
|||
protected Tenant savedTenant; |
|||
protected User tenantAdmin; |
|||
|
|||
protected Device savedDevice; |
|||
protected String accessToken; |
|||
|
|||
protected DeviceProfile deviceProfile; |
|||
|
|||
protected void processAfterTest() throws Exception { |
|||
loginSysAdmin(); |
|||
if (savedTenant != null) { |
|||
doDelete("/api/tenant/" + savedTenant.getId().getId().toString()).andExpect(status().isOk()); |
|||
} |
|||
} |
|||
|
|||
protected List<TransportProtos.KeyValueProto> getKvProtos(List<String> expectedKeys) { |
|||
List<TransportProtos.KeyValueProto> keyValueProtos = new ArrayList<>(); |
|||
TransportProtos.KeyValueProto strKeyValueProto = getKeyValueProto(expectedKeys.get(0), "value1", TransportProtos.KeyValueType.STRING_V); |
|||
TransportProtos.KeyValueProto boolKeyValueProto = getKeyValueProto(expectedKeys.get(1), "true", TransportProtos.KeyValueType.BOOLEAN_V); |
|||
TransportProtos.KeyValueProto dblKeyValueProto = getKeyValueProto(expectedKeys.get(2), "3.0", TransportProtos.KeyValueType.DOUBLE_V); |
|||
TransportProtos.KeyValueProto longKeyValueProto = getKeyValueProto(expectedKeys.get(3), "4", TransportProtos.KeyValueType.LONG_V); |
|||
TransportProtos.KeyValueProto jsonKeyValueProto = getKeyValueProto(expectedKeys.get(4), "{\"someNumber\": 42, \"someArray\": [1,2,3], \"someNestedObject\": {\"key\": \"value\"}}", TransportProtos.KeyValueType.JSON_V); |
|||
keyValueProtos.add(strKeyValueProto); |
|||
keyValueProtos.add(boolKeyValueProto); |
|||
keyValueProtos.add(dblKeyValueProto); |
|||
keyValueProtos.add(longKeyValueProto); |
|||
keyValueProtos.add(jsonKeyValueProto); |
|||
return keyValueProtos; |
|||
} |
|||
|
|||
protected TransportProtos.KeyValueProto getKeyValueProto(String key, String strValue, TransportProtos.KeyValueType type) { |
|||
TransportProtos.KeyValueProto.Builder keyValueProtoBuilder = TransportProtos.KeyValueProto.newBuilder(); |
|||
keyValueProtoBuilder.setKey(key); |
|||
keyValueProtoBuilder.setType(type); |
|||
switch (type) { |
|||
case BOOLEAN_V: |
|||
keyValueProtoBuilder.setBoolV(Boolean.parseBoolean(strValue)); |
|||
break; |
|||
case LONG_V: |
|||
keyValueProtoBuilder.setLongV(Long.parseLong(strValue)); |
|||
break; |
|||
case DOUBLE_V: |
|||
keyValueProtoBuilder.setDoubleV(Double.parseDouble(strValue)); |
|||
break; |
|||
case STRING_V: |
|||
keyValueProtoBuilder.setStringV(strValue); |
|||
break; |
|||
case JSON_V: |
|||
keyValueProtoBuilder.setJsonV(strValue); |
|||
break; |
|||
} |
|||
return keyValueProtoBuilder.build(); |
|||
} |
|||
|
|||
protected <T> T doExecuteWithRetriesAndInterval(SupplierWithThrowable<T> supplier, int retries, int intervalMs) throws Exception { |
|||
int count = 0; |
|||
T result = null; |
|||
Throwable lastException = null; |
|||
while (count < retries) { |
|||
try { |
|||
result = supplier.get(); |
|||
if (result != null) { |
|||
return result; |
|||
} |
|||
} catch (Throwable e) { |
|||
lastException = e; |
|||
} |
|||
count++; |
|||
if (count < retries) { |
|||
Thread.sleep(intervalMs); |
|||
} |
|||
} |
|||
if (lastException != null) { |
|||
throw new RuntimeException(lastException); |
|||
} else { |
|||
return result; |
|||
} |
|||
} |
|||
|
|||
@FunctionalInterface |
|||
public interface SupplierWithThrowable<T> { |
|||
T get() throws Throwable; |
|||
} |
|||
} |
|||
@ -0,0 +1,175 @@ |
|||
/** |
|||
* 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.coap; |
|||
|
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.eclipse.californium.core.CoapClient; |
|||
import org.junit.Assert; |
|||
import org.springframework.util.StringUtils; |
|||
import org.thingsboard.server.common.data.CoapDeviceType; |
|||
import org.thingsboard.server.common.data.Device; |
|||
import org.thingsboard.server.common.data.DeviceProfile; |
|||
import org.thingsboard.server.common.data.DeviceProfileProvisionType; |
|||
import org.thingsboard.server.common.data.DeviceProfileType; |
|||
import org.thingsboard.server.common.data.DeviceTransportType; |
|||
import org.thingsboard.server.common.data.Tenant; |
|||
import org.thingsboard.server.common.data.TransportPayloadType; |
|||
import org.thingsboard.server.common.data.User; |
|||
import org.thingsboard.server.common.data.device.profile.AllowCreateNewDevicesDeviceProfileProvisionConfiguration; |
|||
import org.thingsboard.server.common.data.device.profile.CheckPreProvisionedDevicesDeviceProfileProvisionConfiguration; |
|||
import org.thingsboard.server.common.data.device.profile.CoapDeviceProfileTransportConfiguration; |
|||
import org.thingsboard.server.common.data.device.profile.CoapDeviceTypeConfiguration; |
|||
import org.thingsboard.server.common.data.device.profile.DefaultCoapDeviceTypeConfiguration; |
|||
import org.thingsboard.server.common.data.device.profile.DefaultDeviceProfileConfiguration; |
|||
import org.thingsboard.server.common.data.device.profile.DeviceProfileData; |
|||
import org.thingsboard.server.common.data.device.profile.DeviceProfileProvisionConfiguration; |
|||
import org.thingsboard.server.common.data.device.profile.DisabledDeviceProfileProvisionConfiguration; |
|||
import org.thingsboard.server.common.data.device.profile.EfentoCoapDeviceTypeConfiguration; |
|||
import org.thingsboard.server.common.data.device.profile.JsonTransportPayloadConfiguration; |
|||
import org.thingsboard.server.common.data.device.profile.ProtoTransportPayloadConfiguration; |
|||
import org.thingsboard.server.common.data.device.profile.TransportPayloadTypeConfiguration; |
|||
import org.thingsboard.server.common.data.security.Authority; |
|||
import org.thingsboard.server.common.data.security.DeviceCredentials; |
|||
import org.thingsboard.server.common.msg.session.FeatureType; |
|||
import org.thingsboard.server.transport.AbstractTransportIntegrationTest; |
|||
|
|||
import static org.junit.Assert.assertEquals; |
|||
import static org.junit.Assert.assertNotNull; |
|||
|
|||
@Slf4j |
|||
public abstract class AbstractCoapIntegrationTest extends AbstractTransportIntegrationTest { |
|||
|
|||
protected void processBeforeTest(String deviceName, CoapDeviceType coapDeviceType, TransportPayloadType payloadType) throws Exception { |
|||
this.processBeforeTest(deviceName, coapDeviceType, payloadType, null, null, DeviceProfileProvisionType.DISABLED, null, null); |
|||
} |
|||
|
|||
protected void processBeforeTest(String deviceName, |
|||
CoapDeviceType coapDeviceType, |
|||
TransportPayloadType payloadType, |
|||
String telemetryProtoSchema, |
|||
String attributesProtoSchema, |
|||
DeviceProfileProvisionType provisionType, |
|||
String provisionKey, String provisionSecret |
|||
) throws Exception { |
|||
loginSysAdmin(); |
|||
|
|||
Tenant tenant = new Tenant(); |
|||
tenant.setTitle("My tenant"); |
|||
savedTenant = doPost("/api/tenant", tenant, Tenant.class); |
|||
Assert.assertNotNull(savedTenant); |
|||
|
|||
tenantAdmin = new User(); |
|||
tenantAdmin.setAuthority(Authority.TENANT_ADMIN); |
|||
tenantAdmin.setTenantId(savedTenant.getId()); |
|||
tenantAdmin.setEmail("tenant" + atomicInteger.getAndIncrement() + "@thingsboard.org"); |
|||
tenantAdmin.setFirstName("Joe"); |
|||
tenantAdmin.setLastName("Downs"); |
|||
|
|||
tenantAdmin = createUserAndLogin(tenantAdmin, "testPassword1"); |
|||
|
|||
Device device = new Device(); |
|||
device.setName(deviceName); |
|||
device.setType("default"); |
|||
|
|||
if (coapDeviceType != null) { |
|||
DeviceProfile coapDeviceProfile = createCoapDeviceProfile(payloadType, coapDeviceType, attributesProtoSchema, provisionType, provisionKey, provisionSecret, telemetryProtoSchema); |
|||
deviceProfile = doPost("/api/deviceProfile", coapDeviceProfile, DeviceProfile.class); |
|||
device.setType(deviceProfile.getName()); |
|||
device.setDeviceProfileId(deviceProfile.getId()); |
|||
} |
|||
|
|||
savedDevice = doPost("/api/device", device, Device.class); |
|||
|
|||
DeviceCredentials deviceCredentials = |
|||
doGet("/api/device/" + savedDevice.getId().getId().toString() + "/credentials", DeviceCredentials.class); |
|||
|
|||
assertEquals(savedDevice.getId(), deviceCredentials.getDeviceId()); |
|||
accessToken = deviceCredentials.getCredentialsId(); |
|||
assertNotNull(accessToken); |
|||
|
|||
} |
|||
|
|||
protected DeviceProfile createCoapDeviceProfile(TransportPayloadType transportPayloadType, CoapDeviceType coapDeviceType, |
|||
String attributesProtoSchema, DeviceProfileProvisionType provisionType, |
|||
String provisionKey, String provisionSecret, String telemetryProtoSchema) { |
|||
DeviceProfile deviceProfile = new DeviceProfile(); |
|||
deviceProfile.setName(transportPayloadType.name()); |
|||
deviceProfile.setType(DeviceProfileType.DEFAULT); |
|||
deviceProfile.setProvisionType(provisionType); |
|||
deviceProfile.setProvisionDeviceKey(provisionKey); |
|||
deviceProfile.setDescription(transportPayloadType.name() + " Test"); |
|||
DeviceProfileData deviceProfileData = new DeviceProfileData(); |
|||
DefaultDeviceProfileConfiguration configuration = new DefaultDeviceProfileConfiguration(); |
|||
deviceProfile.setTransportType(DeviceTransportType.COAP); |
|||
CoapDeviceProfileTransportConfiguration coapDeviceProfileTransportConfiguration = new CoapDeviceProfileTransportConfiguration(); |
|||
CoapDeviceTypeConfiguration coapDeviceTypeConfiguration; |
|||
if (CoapDeviceType.DEFAULT.equals(coapDeviceType)) { |
|||
DefaultCoapDeviceTypeConfiguration defaultCoapDeviceTypeConfiguration = new DefaultCoapDeviceTypeConfiguration(); |
|||
TransportPayloadTypeConfiguration transportPayloadTypeConfiguration; |
|||
if (TransportPayloadType.PROTOBUF.equals(transportPayloadType)) { |
|||
ProtoTransportPayloadConfiguration protoTransportPayloadConfiguration = new ProtoTransportPayloadConfiguration(); |
|||
if (StringUtils.isEmpty(telemetryProtoSchema)) { |
|||
telemetryProtoSchema = DEVICE_TELEMETRY_PROTO_SCHEMA; |
|||
} |
|||
if (StringUtils.isEmpty(attributesProtoSchema)) { |
|||
attributesProtoSchema = DEVICE_ATTRIBUTES_PROTO_SCHEMA; |
|||
} |
|||
protoTransportPayloadConfiguration.setDeviceTelemetryProtoSchema(telemetryProtoSchema); |
|||
protoTransportPayloadConfiguration.setDeviceAttributesProtoSchema(attributesProtoSchema); |
|||
transportPayloadTypeConfiguration = protoTransportPayloadConfiguration; |
|||
} else { |
|||
transportPayloadTypeConfiguration = new JsonTransportPayloadConfiguration(); |
|||
} |
|||
defaultCoapDeviceTypeConfiguration.setTransportPayloadTypeConfiguration(transportPayloadTypeConfiguration); |
|||
coapDeviceTypeConfiguration = defaultCoapDeviceTypeConfiguration; |
|||
} else { |
|||
coapDeviceTypeConfiguration = new EfentoCoapDeviceTypeConfiguration(); |
|||
} |
|||
coapDeviceProfileTransportConfiguration.setCoapDeviceTypeConfiguration(coapDeviceTypeConfiguration); |
|||
deviceProfileData.setTransportConfiguration(coapDeviceProfileTransportConfiguration); |
|||
DeviceProfileProvisionConfiguration provisionConfiguration; |
|||
switch (provisionType) { |
|||
case ALLOW_CREATE_NEW_DEVICES: |
|||
provisionConfiguration = new AllowCreateNewDevicesDeviceProfileProvisionConfiguration(provisionSecret); |
|||
break; |
|||
case CHECK_PRE_PROVISIONED_DEVICES: |
|||
provisionConfiguration = new CheckPreProvisionedDevicesDeviceProfileProvisionConfiguration(provisionSecret); |
|||
break; |
|||
case DISABLED: |
|||
default: |
|||
provisionConfiguration = new DisabledDeviceProfileProvisionConfiguration(provisionSecret); |
|||
break; |
|||
} |
|||
deviceProfileData.setProvisionConfiguration(provisionConfiguration); |
|||
deviceProfileData.setConfiguration(configuration); |
|||
deviceProfile.setProfileData(deviceProfileData); |
|||
deviceProfile.setDefault(false); |
|||
deviceProfile.setDefaultRuleChainId(null); |
|||
return deviceProfile; |
|||
} |
|||
|
|||
protected CoapClient getCoapClient(FeatureType featureType) { |
|||
return new CoapClient(getFeatureTokenUrl(accessToken, featureType)); |
|||
} |
|||
|
|||
protected CoapClient getCoapClient(String featureTokenUrl) { |
|||
return new CoapClient(featureTokenUrl); |
|||
} |
|||
|
|||
protected String getFeatureTokenUrl(String token, FeatureType featureType) { |
|||
return COAP_BASE_URL + token + "/" + featureType.name().toLowerCase(); |
|||
} |
|||
} |
|||
@ -0,0 +1,62 @@ |
|||
/** |
|||
* 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.coap.attributes; |
|||
|
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.thingsboard.server.transport.coap.AbstractCoapIntegrationTest; |
|||
import org.thingsboard.server.common.data.CoapDeviceType; |
|||
import org.thingsboard.server.common.data.TransportPayloadType; |
|||
import org.thingsboard.server.gen.transport.TransportProtos; |
|||
|
|||
import java.util.ArrayList; |
|||
import java.util.List; |
|||
|
|||
@Slf4j |
|||
public abstract class AbstractCoapAttributesIntegrationTest extends AbstractCoapIntegrationTest { |
|||
|
|||
protected static final String POST_ATTRIBUTES_PAYLOAD = "{\"attribute1\":\"value1\",\"attribute2\":true,\"attribute3\":42.0,\"attribute4\":73," + |
|||
"\"attribute5\":{\"someNumber\":42,\"someArray\":[1,2,3],\"someNestedObject\":{\"key\":\"value\"}}}"; |
|||
|
|||
protected void processBeforeTest(String deviceName, CoapDeviceType coapDeviceType, TransportPayloadType payloadType) throws Exception { |
|||
super.processBeforeTest(deviceName, coapDeviceType, payloadType); |
|||
} |
|||
|
|||
protected void processAfterTest() throws Exception { |
|||
super.processAfterTest(); |
|||
} |
|||
|
|||
protected List<TransportProtos.TsKvProto> getTsKvProtoList() { |
|||
TransportProtos.TsKvProto tsKvProtoAttribute1 = getTsKvProto("attribute1", "value1", TransportProtos.KeyValueType.STRING_V); |
|||
TransportProtos.TsKvProto tsKvProtoAttribute2 = getTsKvProto("attribute2", "true", TransportProtos.KeyValueType.BOOLEAN_V); |
|||
TransportProtos.TsKvProto tsKvProtoAttribute3 = getTsKvProto("attribute3", "42.0", TransportProtos.KeyValueType.DOUBLE_V); |
|||
TransportProtos.TsKvProto tsKvProtoAttribute4 = getTsKvProto("attribute4", "73", TransportProtos.KeyValueType.LONG_V); |
|||
TransportProtos.TsKvProto tsKvProtoAttribute5 = getTsKvProto("attribute5", "{\"someNumber\":42,\"someArray\":[1,2,3],\"someNestedObject\":{\"key\":\"value\"}}", TransportProtos.KeyValueType.JSON_V); |
|||
List<TransportProtos.TsKvProto> tsKvProtoList = new ArrayList<>(); |
|||
tsKvProtoList.add(tsKvProtoAttribute1); |
|||
tsKvProtoList.add(tsKvProtoAttribute2); |
|||
tsKvProtoList.add(tsKvProtoAttribute3); |
|||
tsKvProtoList.add(tsKvProtoAttribute4); |
|||
tsKvProtoList.add(tsKvProtoAttribute5); |
|||
return tsKvProtoList; |
|||
} |
|||
|
|||
protected TransportProtos.TsKvProto getTsKvProto(String key, String value, TransportProtos.KeyValueType keyValueType) { |
|||
TransportProtos.TsKvProto.Builder tsKvProtoBuilder = TransportProtos.TsKvProto.newBuilder(); |
|||
TransportProtos.KeyValueProto keyValueProto = getKeyValueProto(key, value, keyValueType); |
|||
tsKvProtoBuilder.setKv(keyValueProto); |
|||
return tsKvProtoBuilder.build(); |
|||
} |
|||
} |
|||
@ -0,0 +1,96 @@ |
|||
/** |
|||
* 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.coap.attributes.request; |
|||
|
|||
import com.fasterxml.jackson.core.type.TypeReference; |
|||
import com.google.protobuf.InvalidProtocolBufferException; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.eclipse.californium.core.CoapClient; |
|||
import org.eclipse.californium.core.CoapResponse; |
|||
import org.eclipse.californium.core.coap.CoAP; |
|||
import org.eclipse.californium.core.coap.MediaTypeRegistry; |
|||
import org.junit.After; |
|||
import org.junit.Before; |
|||
import org.junit.Test; |
|||
import org.thingsboard.server.transport.coap.attributes.AbstractCoapAttributesIntegrationTest; |
|||
import org.thingsboard.server.common.msg.session.FeatureType; |
|||
import org.thingsboard.server.dao.util.mapping.JacksonUtil; |
|||
|
|||
import java.nio.charset.StandardCharsets; |
|||
import java.util.List; |
|||
|
|||
import static org.junit.Assert.assertEquals; |
|||
import static org.junit.Assert.assertNotNull; |
|||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; |
|||
|
|||
@Slf4j |
|||
public abstract class AbstractCoapAttributesRequestIntegrationTest extends AbstractCoapAttributesIntegrationTest { |
|||
|
|||
protected static final long CLIENT_REQUEST_TIMEOUT = 60000L; |
|||
|
|||
@Before |
|||
public void beforeTest() throws Exception { |
|||
processBeforeTest("Test Request attribute values from the server", null, null); |
|||
} |
|||
|
|||
@After |
|||
public void afterTest() throws Exception { |
|||
processAfterTest(); |
|||
} |
|||
|
|||
@Test |
|||
public void testRequestAttributesValuesFromTheServer() throws Exception { |
|||
processTestRequestAttributesValuesFromTheServer(); |
|||
} |
|||
|
|||
protected void processTestRequestAttributesValuesFromTheServer() throws Exception { |
|||
postAttributes(); |
|||
|
|||
long start = System.currentTimeMillis(); |
|||
long end = System.currentTimeMillis() + 5000; |
|||
|
|||
List<String> savedAttributeKeys = null; |
|||
while (start <= end) { |
|||
savedAttributeKeys = doGetAsyncTyped("/api/plugins/telemetry/DEVICE/" + savedDevice.getId().getId() + "/keys/attributes/CLIENT_SCOPE", new TypeReference<>() {}); |
|||
if (savedAttributeKeys.size() == 5) { |
|||
break; |
|||
} |
|||
Thread.sleep(100); |
|||
start += 100; |
|||
} |
|||
assertNotNull(savedAttributeKeys); |
|||
|
|||
String keys = "attribute1,attribute2,attribute3,attribute4,attribute5"; |
|||
String featureTokenUrl = getFeatureTokenUrl(accessToken, FeatureType.ATTRIBUTES) + "?clientKeys=" + keys + "&sharedKeys=" + keys; |
|||
CoapClient client = getCoapClient(featureTokenUrl); |
|||
|
|||
CoapResponse getAttributesResponse = client.setTimeout(CLIENT_REQUEST_TIMEOUT).get(); |
|||
validateResponse(getAttributesResponse); |
|||
} |
|||
|
|||
protected void postAttributes() throws Exception { |
|||
doPostAsync("/api/plugins/telemetry/DEVICE/" + savedDevice.getId().getId() + "/attributes/SHARED_SCOPE", POST_ATTRIBUTES_PAYLOAD, String.class, status().isOk()); |
|||
CoapClient client = getCoapClient(FeatureType.ATTRIBUTES); |
|||
CoapResponse coapResponse = client.setTimeout(CLIENT_REQUEST_TIMEOUT).post(POST_ATTRIBUTES_PAYLOAD.getBytes(), MediaTypeRegistry.APPLICATION_JSON); |
|||
assertEquals(CoAP.ResponseCode.CREATED, coapResponse.getCode()); |
|||
} |
|||
|
|||
protected void validateResponse(CoapResponse getAttributesResponse) throws InvalidProtocolBufferException { |
|||
assertEquals(CoAP.ResponseCode.CONTENT, getAttributesResponse.getCode()); |
|||
String expectedRequestPayload = "{\"client\":{\"attribute1\":\"value1\",\"attribute2\":true,\"attribute3\":42.0,\"attribute4\":73,\"attribute5\":{\"someNumber\":42,\"someArray\":[1,2,3],\"someNestedObject\":{\"key\":\"value\"}}},\"shared\":{\"attribute1\":\"value1\",\"attribute2\":true,\"attribute3\":42.0,\"attribute4\":73,\"attribute5\":{\"someNumber\":42,\"someArray\":[1,2,3],\"someNestedObject\":{\"key\":\"value\"}}}}"; |
|||
assertEquals(JacksonUtil.toJsonNode(expectedRequestPayload), JacksonUtil.toJsonNode(new String(getAttributesResponse.getPayload(), StandardCharsets.UTF_8))); |
|||
} |
|||
} |
|||
@ -0,0 +1,42 @@ |
|||
/** |
|||
* 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.coap.attributes.request; |
|||
|
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.junit.After; |
|||
import org.junit.Before; |
|||
import org.junit.Test; |
|||
import org.thingsboard.server.common.data.CoapDeviceType; |
|||
import org.thingsboard.server.common.data.TransportPayloadType; |
|||
|
|||
@Slf4j |
|||
public abstract class AbstractCoapAttributesRequestJsonIntegrationTest extends AbstractCoapAttributesRequestIntegrationTest { |
|||
|
|||
@Before |
|||
public void beforeTest() throws Exception { |
|||
processBeforeTest("Test Request attribute values from the server json", CoapDeviceType.DEFAULT, TransportPayloadType.JSON); |
|||
} |
|||
|
|||
@After |
|||
public void afterTest() throws Exception { |
|||
processAfterTest(); |
|||
} |
|||
|
|||
@Test |
|||
public void testRequestAttributesValuesFromTheServer() throws Exception { |
|||
super.testRequestAttributesValuesFromTheServer(); |
|||
} |
|||
} |
|||
@ -0,0 +1,153 @@ |
|||
/** |
|||
* 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.coap.attributes.request; |
|||
|
|||
import com.github.os72.protobuf.dynamic.DynamicSchema; |
|||
import com.google.protobuf.Descriptors; |
|||
import com.google.protobuf.DynamicMessage; |
|||
import com.google.protobuf.InvalidProtocolBufferException; |
|||
import com.squareup.wire.schema.internal.parser.ProtoFileElement; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.eclipse.californium.core.CoapClient; |
|||
import org.eclipse.californium.core.CoapResponse; |
|||
import org.eclipse.californium.core.coap.CoAP; |
|||
import org.eclipse.californium.core.coap.MediaTypeRegistry; |
|||
import org.junit.After; |
|||
import org.junit.Test; |
|||
import org.thingsboard.server.common.data.CoapDeviceType; |
|||
import org.thingsboard.server.common.data.DeviceProfileProvisionType; |
|||
import org.thingsboard.server.common.data.TransportPayloadType; |
|||
import org.thingsboard.server.common.data.device.profile.CoapDeviceProfileTransportConfiguration; |
|||
import org.thingsboard.server.common.data.device.profile.CoapDeviceTypeConfiguration; |
|||
import org.thingsboard.server.common.data.device.profile.DefaultCoapDeviceTypeConfiguration; |
|||
import org.thingsboard.server.common.data.device.profile.DeviceProfileTransportConfiguration; |
|||
import org.thingsboard.server.common.data.device.profile.ProtoTransportPayloadConfiguration; |
|||
import org.thingsboard.server.common.data.device.profile.TransportPayloadTypeConfiguration; |
|||
import org.thingsboard.server.common.msg.session.FeatureType; |
|||
import org.thingsboard.server.gen.transport.TransportProtos; |
|||
|
|||
import java.util.List; |
|||
import java.util.stream.Collectors; |
|||
|
|||
import static org.junit.Assert.assertEquals; |
|||
import static org.junit.Assert.assertNotNull; |
|||
import static org.junit.Assert.assertTrue; |
|||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; |
|||
|
|||
@Slf4j |
|||
public abstract class AbstractCoapAttributesRequestProtoIntegrationTest extends AbstractCoapAttributesRequestIntegrationTest { |
|||
|
|||
public static final String ATTRIBUTES_SCHEMA_STR = "syntax =\"proto3\";\n" + |
|||
"\n" + |
|||
"package test;\n" + |
|||
"\n" + |
|||
"message PostAttributes {\n" + |
|||
" string attribute1 = 1;\n" + |
|||
" bool attribute2 = 2;\n" + |
|||
" double attribute3 = 3;\n" + |
|||
" int32 attribute4 = 4;\n" + |
|||
" JsonObject attribute5 = 5;\n" + |
|||
"\n" + |
|||
" message JsonObject {\n" + |
|||
" int32 someNumber = 6;\n" + |
|||
" repeated int32 someArray = 7;\n" + |
|||
" NestedJsonObject someNestedObject = 8;\n" + |
|||
" message NestedJsonObject {\n" + |
|||
" string key = 9;\n" + |
|||
" }\n" + |
|||
" }\n" + |
|||
"}"; |
|||
|
|||
@After |
|||
public void afterTest() throws Exception { |
|||
processAfterTest(); |
|||
} |
|||
|
|||
@Test |
|||
public void testRequestAttributesValuesFromTheServer() throws Exception { |
|||
super.processBeforeTest("Test Request attribute values from the server proto", CoapDeviceType.DEFAULT, |
|||
TransportPayloadType.PROTOBUF, null, ATTRIBUTES_SCHEMA_STR, DeviceProfileProvisionType.DISABLED, null, null); |
|||
processTestRequestAttributesValuesFromTheServer(); |
|||
} |
|||
|
|||
protected void postAttributes() throws Exception { |
|||
doPostAsync("/api/plugins/telemetry/DEVICE/" + savedDevice.getId().getId() + "/attributes/SHARED_SCOPE", POST_ATTRIBUTES_PAYLOAD, String.class, status().isOk()); |
|||
DeviceProfileTransportConfiguration transportConfiguration = deviceProfile.getProfileData().getTransportConfiguration(); |
|||
assertTrue(transportConfiguration instanceof CoapDeviceProfileTransportConfiguration); |
|||
CoapDeviceProfileTransportConfiguration coapTransportConfiguration = (CoapDeviceProfileTransportConfiguration) transportConfiguration; |
|||
CoapDeviceTypeConfiguration coapDeviceTypeConfiguration = coapTransportConfiguration.getCoapDeviceTypeConfiguration(); |
|||
assertTrue(coapDeviceTypeConfiguration instanceof DefaultCoapDeviceTypeConfiguration); |
|||
DefaultCoapDeviceTypeConfiguration defaultCoapDeviceTypeConfiguration = (DefaultCoapDeviceTypeConfiguration) coapDeviceTypeConfiguration; |
|||
TransportPayloadTypeConfiguration transportPayloadTypeConfiguration = defaultCoapDeviceTypeConfiguration.getTransportPayloadTypeConfiguration(); |
|||
assertTrue(transportPayloadTypeConfiguration instanceof ProtoTransportPayloadConfiguration); |
|||
ProtoTransportPayloadConfiguration protoTransportPayloadConfiguration = (ProtoTransportPayloadConfiguration) transportPayloadTypeConfiguration; |
|||
ProtoFileElement transportProtoSchema = protoTransportPayloadConfiguration.getTransportProtoSchema(ATTRIBUTES_SCHEMA_STR); |
|||
DynamicSchema attributesSchema = protoTransportPayloadConfiguration.getDynamicSchema(transportProtoSchema, ProtoTransportPayloadConfiguration.ATTRIBUTES_PROTO_SCHEMA); |
|||
|
|||
DynamicMessage.Builder nestedJsonObjectBuilder = attributesSchema.newMessageBuilder("PostAttributes.JsonObject.NestedJsonObject"); |
|||
Descriptors.Descriptor nestedJsonObjectBuilderDescriptor = nestedJsonObjectBuilder.getDescriptorForType(); |
|||
assertNotNull(nestedJsonObjectBuilderDescriptor); |
|||
DynamicMessage nestedJsonObject = nestedJsonObjectBuilder.setField(nestedJsonObjectBuilderDescriptor.findFieldByName("key"), "value").build(); |
|||
|
|||
DynamicMessage.Builder jsonObjectBuilder = attributesSchema.newMessageBuilder("PostAttributes.JsonObject"); |
|||
Descriptors.Descriptor jsonObjectBuilderDescriptor = jsonObjectBuilder.getDescriptorForType(); |
|||
assertNotNull(jsonObjectBuilderDescriptor); |
|||
DynamicMessage jsonObject = jsonObjectBuilder |
|||
.setField(jsonObjectBuilderDescriptor.findFieldByName("someNumber"), 42) |
|||
.addRepeatedField(jsonObjectBuilderDescriptor.findFieldByName("someArray"), 1) |
|||
.addRepeatedField(jsonObjectBuilderDescriptor.findFieldByName("someArray"), 2) |
|||
.addRepeatedField(jsonObjectBuilderDescriptor.findFieldByName("someArray"), 3) |
|||
.setField(jsonObjectBuilderDescriptor.findFieldByName("someNestedObject"), nestedJsonObject) |
|||
.build(); |
|||
|
|||
DynamicMessage.Builder postAttributesBuilder = attributesSchema.newMessageBuilder("PostAttributes"); |
|||
Descriptors.Descriptor postAttributesMsgDescriptor = postAttributesBuilder.getDescriptorForType(); |
|||
assertNotNull(postAttributesMsgDescriptor); |
|||
DynamicMessage postAttributesMsg = postAttributesBuilder |
|||
.setField(postAttributesMsgDescriptor.findFieldByName("attribute1"), "value1") |
|||
.setField(postAttributesMsgDescriptor.findFieldByName("attribute2"), true) |
|||
.setField(postAttributesMsgDescriptor.findFieldByName("attribute3"), 42.0) |
|||
.setField(postAttributesMsgDescriptor.findFieldByName("attribute4"), 73) |
|||
.setField(postAttributesMsgDescriptor.findFieldByName("attribute5"), jsonObject) |
|||
.build(); |
|||
byte[] payload = postAttributesMsg.toByteArray(); |
|||
CoapClient client = getCoapClient(FeatureType.ATTRIBUTES); |
|||
CoapResponse coapResponse = client.setTimeout(CLIENT_REQUEST_TIMEOUT).post(payload, MediaTypeRegistry.APPLICATION_JSON); |
|||
assertEquals(CoAP.ResponseCode.CREATED, coapResponse.getCode()); |
|||
} |
|||
|
|||
protected void validateResponse(CoapResponse getAttributesResponse) throws InvalidProtocolBufferException { |
|||
TransportProtos.GetAttributeResponseMsg expectedAttributesResponse = getExpectedAttributeResponseMsg(); |
|||
TransportProtos.GetAttributeResponseMsg actualAttributesResponse = TransportProtos.GetAttributeResponseMsg.parseFrom(getAttributesResponse.getPayload()); |
|||
assertEquals(expectedAttributesResponse.getRequestId(), actualAttributesResponse.getRequestId()); |
|||
List<TransportProtos.KeyValueProto> expectedClientKeyValueProtos = expectedAttributesResponse.getClientAttributeListList().stream().map(TransportProtos.TsKvProto::getKv).collect(Collectors.toList()); |
|||
List<TransportProtos.KeyValueProto> expectedSharedKeyValueProtos = expectedAttributesResponse.getSharedAttributeListList().stream().map(TransportProtos.TsKvProto::getKv).collect(Collectors.toList()); |
|||
List<TransportProtos.KeyValueProto> actualClientKeyValueProtos = actualAttributesResponse.getClientAttributeListList().stream().map(TransportProtos.TsKvProto::getKv).collect(Collectors.toList()); |
|||
List<TransportProtos.KeyValueProto> actualSharedKeyValueProtos = actualAttributesResponse.getSharedAttributeListList().stream().map(TransportProtos.TsKvProto::getKv).collect(Collectors.toList()); |
|||
assertTrue(actualClientKeyValueProtos.containsAll(expectedClientKeyValueProtos)); |
|||
assertTrue(actualSharedKeyValueProtos.containsAll(expectedSharedKeyValueProtos)); |
|||
} |
|||
|
|||
private TransportProtos.GetAttributeResponseMsg getExpectedAttributeResponseMsg() { |
|||
TransportProtos.GetAttributeResponseMsg.Builder result = TransportProtos.GetAttributeResponseMsg.newBuilder(); |
|||
List<TransportProtos.TsKvProto> tsKvProtoList = getTsKvProtoList(); |
|||
result.addAllClientAttributeList(tsKvProtoList); |
|||
result.addAllSharedAttributeList(tsKvProtoList); |
|||
result.setRequestId(0); |
|||
return result.build(); |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,23 @@ |
|||
/** |
|||
* 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.coap.attributes.request.sql; |
|||
|
|||
import org.thingsboard.server.transport.coap.attributes.request.AbstractCoapAttributesRequestJsonIntegrationTest; |
|||
import org.thingsboard.server.dao.service.DaoSqlTest; |
|||
|
|||
@DaoSqlTest |
|||
public class CoapAttributesRequestJsonSqlIntegrationTest extends AbstractCoapAttributesRequestJsonIntegrationTest { |
|||
} |
|||
@ -0,0 +1,23 @@ |
|||
/** |
|||
* 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.coap.attributes.request.sql; |
|||
|
|||
import org.thingsboard.server.transport.coap.attributes.request.AbstractCoapAttributesRequestProtoIntegrationTest; |
|||
import org.thingsboard.server.dao.service.DaoSqlTest; |
|||
|
|||
@DaoSqlTest |
|||
public class CoapAttributesRequestProtoSqlIntegrationTest extends AbstractCoapAttributesRequestProtoIntegrationTest { |
|||
} |
|||
@ -0,0 +1,23 @@ |
|||
/** |
|||
* 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.coap.attributes.request.sql; |
|||
|
|||
import org.thingsboard.server.transport.coap.attributes.request.AbstractCoapAttributesRequestIntegrationTest; |
|||
import org.thingsboard.server.dao.service.DaoSqlTest; |
|||
|
|||
@DaoSqlTest |
|||
public class CoapAttributesRequestSqlIntegrationTest extends AbstractCoapAttributesRequestIntegrationTest { |
|||
} |
|||
@ -0,0 +1,141 @@ |
|||
/** |
|||
* 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.coap.attributes.updates; |
|||
|
|||
import com.google.protobuf.InvalidProtocolBufferException; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.eclipse.californium.core.CoapClient; |
|||
import org.eclipse.californium.core.CoapHandler; |
|||
import org.eclipse.californium.core.CoapObserveRelation; |
|||
import org.eclipse.californium.core.CoapResponse; |
|||
import org.eclipse.californium.core.coap.CoAP; |
|||
import org.eclipse.californium.core.coap.Request; |
|||
import org.junit.After; |
|||
import org.junit.Before; |
|||
import org.junit.Test; |
|||
import org.thingsboard.server.transport.coap.attributes.AbstractCoapAttributesIntegrationTest; |
|||
import org.thingsboard.server.common.msg.session.FeatureType; |
|||
import org.thingsboard.server.dao.util.mapping.JacksonUtil; |
|||
|
|||
import java.nio.charset.StandardCharsets; |
|||
import java.util.concurrent.CountDownLatch; |
|||
import java.util.concurrent.TimeUnit; |
|||
|
|||
import static org.junit.Assert.assertEquals; |
|||
import static org.junit.Assert.assertNotNull; |
|||
import static org.junit.Assert.assertTrue; |
|||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; |
|||
|
|||
@Slf4j |
|||
public abstract class AbstractCoapAttributesUpdatesIntegrationTest extends AbstractCoapAttributesIntegrationTest { |
|||
|
|||
private static final String RESPONSE_ATTRIBUTES_PAYLOAD_DELETED = "{\"deleted\":[\"attribute5\"]}"; |
|||
|
|||
@Before |
|||
public void beforeTest() throws Exception { |
|||
processBeforeTest("Test Subscribe to attribute updates", null, null); |
|||
} |
|||
|
|||
@After |
|||
public void afterTest() throws Exception { |
|||
processAfterTest(); |
|||
} |
|||
|
|||
@Test |
|||
public void testSubscribeToAttributesUpdatesFromTheServer() throws Exception { |
|||
processTestSubscribeToAttributesUpdates(); |
|||
} |
|||
|
|||
protected void processTestSubscribeToAttributesUpdates() throws Exception { |
|||
|
|||
CoapClient client = getCoapClient(FeatureType.ATTRIBUTES); |
|||
|
|||
CountDownLatch latch = new CountDownLatch(1); |
|||
TestCoapCallback testCoapCallback = new TestCoapCallback(latch); |
|||
|
|||
Request request = Request.newGet().setObserve(); |
|||
request.setType(CoAP.Type.CON); |
|||
CoapObserveRelation observeRelation = client.observe(request, testCoapCallback); |
|||
|
|||
Thread.sleep(1000); |
|||
|
|||
doPostAsync("/api/plugins/telemetry/DEVICE/" + savedDevice.getId().getId() + "/attributes/SHARED_SCOPE", POST_ATTRIBUTES_PAYLOAD, String.class, status().isOk()); |
|||
latch.await(3, TimeUnit.SECONDS); |
|||
|
|||
validateUpdateAttributesResponse(testCoapCallback); |
|||
|
|||
latch = new CountDownLatch(1); |
|||
|
|||
doDelete("/api/plugins/telemetry/DEVICE/" + savedDevice.getId().getId() + "/SHARED_SCOPE?keys=attribute5", String.class); |
|||
latch.await(3, TimeUnit.SECONDS); |
|||
|
|||
validateDeleteAttributesResponse(testCoapCallback); |
|||
|
|||
observeRelation.proactiveCancel(); |
|||
assertTrue(observeRelation.isCanceled()); |
|||
} |
|||
|
|||
protected void validateUpdateAttributesResponse(TestCoapCallback callback) throws InvalidProtocolBufferException { |
|||
assertNotNull(callback.getPayloadBytes()); |
|||
assertNotNull(callback.getObserve()); |
|||
assertEquals(0, callback.getObserve().intValue()); |
|||
String response = new String(callback.getPayloadBytes(), StandardCharsets.UTF_8); |
|||
assertEquals(JacksonUtil.toJsonNode(POST_ATTRIBUTES_PAYLOAD), JacksonUtil.toJsonNode(response)); |
|||
} |
|||
|
|||
protected void validateDeleteAttributesResponse(TestCoapCallback callback) throws InvalidProtocolBufferException { |
|||
assertNotNull(callback.getPayloadBytes()); |
|||
assertNotNull(callback.getObserve()); |
|||
assertEquals(1, callback.getObserve().intValue()); |
|||
String response = new String(callback.getPayloadBytes(), StandardCharsets.UTF_8); |
|||
assertEquals(JacksonUtil.toJsonNode(RESPONSE_ATTRIBUTES_PAYLOAD_DELETED), JacksonUtil.toJsonNode(response)); |
|||
} |
|||
|
|||
protected static class TestCoapCallback implements CoapHandler { |
|||
|
|||
private final CountDownLatch latch; |
|||
|
|||
private Integer observe; |
|||
private byte[] payloadBytes; |
|||
|
|||
public byte[] getPayloadBytes() { |
|||
return payloadBytes; |
|||
} |
|||
|
|||
public Integer getObserve() { |
|||
return observe; |
|||
} |
|||
|
|||
private TestCoapCallback(CountDownLatch latch) { |
|||
this.latch = latch; |
|||
} |
|||
|
|||
@Override |
|||
public void onLoad(CoapResponse response) { |
|||
assertNotNull(response.getPayload()); |
|||
assertEquals(response.getCode(), CoAP.ResponseCode.CONTENT); |
|||
observe = response.getOptions().getObserve(); |
|||
payloadBytes = response.getPayload(); |
|||
latch.countDown(); |
|||
} |
|||
|
|||
@Override |
|||
public void onError() { |
|||
log.warn("Command Response Ack Error, No connect"); |
|||
} |
|||
|
|||
} |
|||
} |
|||
@ -0,0 +1,42 @@ |
|||
/** |
|||
* 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.coap.attributes.updates; |
|||
|
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.junit.After; |
|||
import org.junit.Before; |
|||
import org.junit.Test; |
|||
import org.thingsboard.server.common.data.CoapDeviceType; |
|||
import org.thingsboard.server.common.data.TransportPayloadType; |
|||
|
|||
@Slf4j |
|||
public abstract class AbstractCoapAttributesUpdatesJsonIntegrationTest extends AbstractCoapAttributesUpdatesIntegrationTest { |
|||
|
|||
@Before |
|||
public void beforeTest() throws Exception { |
|||
processBeforeTest("Test Subscribe to attribute updates", CoapDeviceType.DEFAULT, TransportPayloadType.JSON); |
|||
} |
|||
|
|||
@After |
|||
public void afterTest() throws Exception { |
|||
processAfterTest(); |
|||
} |
|||
|
|||
@Test |
|||
public void testSubscribeToAttributesUpdatesFromTheServer() throws Exception { |
|||
super.testSubscribeToAttributesUpdatesFromTheServer(); |
|||
} |
|||
} |
|||
@ -0,0 +1,82 @@ |
|||
/** |
|||
* 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.coap.attributes.updates; |
|||
|
|||
import com.google.protobuf.InvalidProtocolBufferException; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.junit.After; |
|||
import org.junit.Before; |
|||
import org.junit.Test; |
|||
import org.thingsboard.server.common.data.CoapDeviceType; |
|||
import org.thingsboard.server.common.data.TransportPayloadType; |
|||
import org.thingsboard.server.gen.transport.TransportProtos; |
|||
|
|||
import java.util.List; |
|||
import java.util.stream.Collectors; |
|||
|
|||
import static org.junit.Assert.assertEquals; |
|||
import static org.junit.Assert.assertNotNull; |
|||
import static org.junit.Assert.assertTrue; |
|||
|
|||
@Slf4j |
|||
public abstract class AbstractCoapAttributesUpdatesProtoIntegrationTest extends AbstractCoapAttributesUpdatesIntegrationTest { |
|||
|
|||
@Before |
|||
public void beforeTest() throws Exception { |
|||
processBeforeTest("Test Subscribe to attribute updates", CoapDeviceType.DEFAULT, TransportPayloadType.PROTOBUF); |
|||
} |
|||
|
|||
@After |
|||
public void afterTest() throws Exception { |
|||
processAfterTest(); |
|||
} |
|||
|
|||
@Test |
|||
public void testSubscribeToAttributesUpdatesFromTheServer() throws Exception { |
|||
processTestSubscribeToAttributesUpdates(); |
|||
} |
|||
|
|||
protected void validateUpdateAttributesResponse(TestCoapCallback callback) throws InvalidProtocolBufferException { |
|||
assertNotNull(callback.getPayloadBytes()); |
|||
TransportProtos.AttributeUpdateNotificationMsg.Builder attributeUpdateNotificationMsgBuilder = TransportProtos.AttributeUpdateNotificationMsg.newBuilder(); |
|||
List<TransportProtos.TsKvProto> tsKvProtoList = getTsKvProtoList(); |
|||
attributeUpdateNotificationMsgBuilder.addAllSharedUpdated(tsKvProtoList); |
|||
|
|||
TransportProtos.AttributeUpdateNotificationMsg expectedAttributeUpdateNotificationMsg = attributeUpdateNotificationMsgBuilder.build(); |
|||
TransportProtos.AttributeUpdateNotificationMsg actualAttributeUpdateNotificationMsg = TransportProtos.AttributeUpdateNotificationMsg.parseFrom(callback.getPayloadBytes()); |
|||
|
|||
List<TransportProtos.KeyValueProto> actualSharedUpdatedList = actualAttributeUpdateNotificationMsg.getSharedUpdatedList().stream().map(TransportProtos.TsKvProto::getKv).collect(Collectors.toList()); |
|||
List<TransportProtos.KeyValueProto> expectedSharedUpdatedList = expectedAttributeUpdateNotificationMsg.getSharedUpdatedList().stream().map(TransportProtos.TsKvProto::getKv).collect(Collectors.toList()); |
|||
|
|||
assertEquals(expectedSharedUpdatedList.size(), actualSharedUpdatedList.size()); |
|||
assertTrue(actualSharedUpdatedList.containsAll(expectedSharedUpdatedList)); |
|||
|
|||
} |
|||
|
|||
protected void validateDeleteAttributesResponse(TestCoapCallback callback) throws InvalidProtocolBufferException { |
|||
assertNotNull(callback.getPayloadBytes()); |
|||
TransportProtos.AttributeUpdateNotificationMsg.Builder attributeUpdateNotificationMsgBuilder = TransportProtos.AttributeUpdateNotificationMsg.newBuilder(); |
|||
attributeUpdateNotificationMsgBuilder.addSharedDeleted("attribute5"); |
|||
|
|||
TransportProtos.AttributeUpdateNotificationMsg expectedAttributeUpdateNotificationMsg = attributeUpdateNotificationMsgBuilder.build(); |
|||
TransportProtos.AttributeUpdateNotificationMsg actualAttributeUpdateNotificationMsg = TransportProtos.AttributeUpdateNotificationMsg.parseFrom(callback.getPayloadBytes()); |
|||
|
|||
assertEquals(expectedAttributeUpdateNotificationMsg.getSharedDeletedList().size(), actualAttributeUpdateNotificationMsg.getSharedDeletedList().size()); |
|||
assertEquals("attribute5", actualAttributeUpdateNotificationMsg.getSharedDeletedList().get(0)); |
|||
|
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,23 @@ |
|||
/** |
|||
* 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.coap.attributes.updates.sql; |
|||
|
|||
import org.thingsboard.server.transport.coap.attributes.updates.AbstractCoapAttributesUpdatesIntegrationTest; |
|||
import org.thingsboard.server.dao.service.DaoSqlTest; |
|||
|
|||
@DaoSqlTest |
|||
public class CoapAttributesUpdatesSqlIntegrationTest extends AbstractCoapAttributesUpdatesIntegrationTest { |
|||
} |
|||
@ -0,0 +1,23 @@ |
|||
/** |
|||
* 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.coap.attributes.updates.sql; |
|||
|
|||
import org.thingsboard.server.transport.coap.attributes.updates.AbstractCoapAttributesUpdatesJsonIntegrationTest; |
|||
import org.thingsboard.server.dao.service.DaoSqlTest; |
|||
|
|||
@DaoSqlTest |
|||
public class CoapAttributesUpdatesSqlJsonIntegrationTest extends AbstractCoapAttributesUpdatesJsonIntegrationTest { |
|||
} |
|||
@ -0,0 +1,23 @@ |
|||
/** |
|||
* 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.coap.attributes.updates.sql; |
|||
|
|||
import org.thingsboard.server.transport.coap.attributes.updates.AbstractCoapAttributesUpdatesProtoIntegrationTest; |
|||
import org.thingsboard.server.dao.service.DaoSqlTest; |
|||
|
|||
@DaoSqlTest |
|||
public class CoapAttributesUpdatesSqlProtoIntegrationTest extends AbstractCoapAttributesUpdatesProtoIntegrationTest { |
|||
} |
|||
@ -0,0 +1,147 @@ |
|||
/** |
|||
* 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.coap.claim; |
|||
|
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.eclipse.californium.core.CoapClient; |
|||
import org.eclipse.californium.core.CoapResponse; |
|||
import org.eclipse.californium.core.coap.CoAP; |
|||
import org.eclipse.californium.core.coap.MediaTypeRegistry; |
|||
import org.eclipse.californium.elements.exception.ConnectorException; |
|||
import org.junit.After; |
|||
import org.junit.Before; |
|||
import org.junit.Test; |
|||
import org.thingsboard.server.transport.coap.AbstractCoapIntegrationTest; |
|||
import org.thingsboard.server.common.data.ClaimRequest; |
|||
import org.thingsboard.server.common.data.Customer; |
|||
import org.thingsboard.server.common.data.Device; |
|||
import org.thingsboard.server.common.data.User; |
|||
import org.thingsboard.server.common.data.security.Authority; |
|||
import org.thingsboard.server.common.msg.session.FeatureType; |
|||
import org.thingsboard.server.dao.device.claim.ClaimResponse; |
|||
import org.thingsboard.server.dao.device.claim.ClaimResult; |
|||
|
|||
import java.io.IOException; |
|||
|
|||
import static org.junit.Assert.assertEquals; |
|||
import static org.junit.Assert.assertNotNull; |
|||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; |
|||
|
|||
@Slf4j |
|||
public abstract class AbstractCoapClaimDeviceTest extends AbstractCoapIntegrationTest { |
|||
|
|||
protected static final String CUSTOMER_USER_PASSWORD = "customerUser123!"; |
|||
|
|||
protected User customerAdmin; |
|||
protected Customer savedCustomer; |
|||
|
|||
@Before |
|||
public void beforeTest() throws Exception { |
|||
super.processBeforeTest("Test Claim device", null, null); |
|||
createCustomerAndUser(); |
|||
} |
|||
|
|||
protected void createCustomerAndUser() throws Exception { |
|||
Customer customer = new Customer(); |
|||
customer.setTenantId(savedTenant.getId()); |
|||
customer.setTitle("Test Claiming Customer"); |
|||
savedCustomer = doPost("/api/customer", customer, Customer.class); |
|||
assertNotNull(savedCustomer); |
|||
assertEquals(savedTenant.getId(), savedCustomer.getTenantId()); |
|||
|
|||
User user = new User(); |
|||
user.setAuthority(Authority.CUSTOMER_USER); |
|||
user.setTenantId(savedTenant.getId()); |
|||
user.setCustomerId(savedCustomer.getId()); |
|||
user.setEmail("customer@thingsboard.org"); |
|||
|
|||
customerAdmin = createUser(user, CUSTOMER_USER_PASSWORD); |
|||
assertNotNull(customerAdmin); |
|||
assertEquals(customerAdmin.getCustomerId(), savedCustomer.getId()); |
|||
} |
|||
|
|||
@After |
|||
public void afterTest() throws Exception { |
|||
super.processAfterTest(); |
|||
} |
|||
|
|||
@Test |
|||
public void testClaimingDevice() throws Exception { |
|||
processTestClaimingDevice(false); |
|||
} |
|||
|
|||
@Test |
|||
public void testClaimingDeviceWithoutSecretAndDuration() throws Exception { |
|||
processTestClaimingDevice(true); |
|||
} |
|||
|
|||
protected void processTestClaimingDevice(boolean emptyPayload) throws Exception { |
|||
log.warn("[testClaimingDevice] Device: {}, Transport type: {}", savedDevice.getName(), savedDevice.getType()); |
|||
CoapClient client = getCoapClient(FeatureType.CLAIM); |
|||
byte[] payloadBytes; |
|||
byte[] failurePayloadBytes; |
|||
if (emptyPayload) { |
|||
payloadBytes = "{}".getBytes(); |
|||
failurePayloadBytes = "{\"durationMs\":1}".getBytes(); |
|||
} else { |
|||
payloadBytes = "{\"secretKey\":\"value\", \"durationMs\":60000}".getBytes(); |
|||
failurePayloadBytes = "{\"secretKey\":\"value\", \"durationMs\":1}".getBytes(); |
|||
} |
|||
validateClaimResponse(emptyPayload, client, payloadBytes, failurePayloadBytes); |
|||
} |
|||
|
|||
protected void validateClaimResponse(boolean emptyPayload, CoapClient client, byte[] payloadBytes, byte[] failurePayloadBytes) throws Exception { |
|||
postClaimRequest(client, failurePayloadBytes); |
|||
|
|||
loginUser(customerAdmin.getName(), CUSTOMER_USER_PASSWORD); |
|||
ClaimRequest claimRequest; |
|||
if (!emptyPayload) { |
|||
claimRequest = new ClaimRequest("value"); |
|||
} else { |
|||
claimRequest = new ClaimRequest(null); |
|||
} |
|||
|
|||
ClaimResponse claimResponse = doExecuteWithRetriesAndInterval( |
|||
() -> doPostClaimAsync("/api/customer/device/" + savedDevice.getName() + "/claim", claimRequest, ClaimResponse.class, status().isBadRequest()), |
|||
20, |
|||
100 |
|||
); |
|||
|
|||
assertEquals(claimResponse, ClaimResponse.FAILURE); |
|||
|
|||
postClaimRequest(client, payloadBytes); |
|||
|
|||
ClaimResult claimResult = doExecuteWithRetriesAndInterval( |
|||
() -> doPostClaimAsync("/api/customer/device/" + savedDevice.getName() + "/claim", claimRequest, ClaimResult.class, status().isOk()), |
|||
20, |
|||
100 |
|||
); |
|||
assertEquals(claimResult.getResponse(), ClaimResponse.SUCCESS); |
|||
Device claimedDevice = claimResult.getDevice(); |
|||
assertNotNull(claimedDevice); |
|||
assertNotNull(claimedDevice.getCustomerId()); |
|||
assertEquals(customerAdmin.getCustomerId(), claimedDevice.getCustomerId()); |
|||
|
|||
claimResponse = doPostClaimAsync("/api/customer/device/" + savedDevice.getName() + "/claim", claimRequest, ClaimResponse.class, status().isBadRequest()); |
|||
assertEquals(claimResponse, ClaimResponse.CLAIMED); |
|||
} |
|||
|
|||
private void postClaimRequest(CoapClient client, byte[] payload) throws IOException, ConnectorException { |
|||
CoapResponse coapResponse = client.setTimeout((long) 60000).post(payload, MediaTypeRegistry.APPLICATION_JSON); |
|||
assertEquals(CoAP.ResponseCode.CREATED, coapResponse.getCode()); |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,48 @@ |
|||
/** |
|||
* 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.coap.claim; |
|||
|
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.junit.After; |
|||
import org.junit.Before; |
|||
import org.junit.Test; |
|||
import org.thingsboard.server.common.data.CoapDeviceType; |
|||
import org.thingsboard.server.common.data.TransportPayloadType; |
|||
|
|||
@Slf4j |
|||
public abstract class AbstractCoapClaimJsonDeviceTest extends AbstractCoapClaimDeviceTest { |
|||
|
|||
@Before |
|||
public void beforeTest() throws Exception { |
|||
super.processBeforeTest("Test Claim device Json", CoapDeviceType.DEFAULT, TransportPayloadType.JSON); |
|||
createCustomerAndUser(); |
|||
} |
|||
|
|||
@After |
|||
public void afterTest() throws Exception { |
|||
super.afterTest(); |
|||
} |
|||
|
|||
@Test |
|||
public void testClaimingDevice() throws Exception { |
|||
super.testClaimingDevice(); |
|||
} |
|||
|
|||
@Test |
|||
public void testClaimingDeviceWithoutSecretAndDuration() throws Exception { |
|||
super.testClaimingDeviceWithoutSecretAndDuration(); |
|||
} |
|||
} |
|||
@ -0,0 +1,81 @@ |
|||
/** |
|||
* 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.coap.claim; |
|||
|
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.eclipse.californium.core.CoapClient; |
|||
import org.junit.After; |
|||
import org.junit.Before; |
|||
import org.junit.Test; |
|||
import org.thingsboard.server.common.data.CoapDeviceType; |
|||
import org.thingsboard.server.common.data.TransportPayloadType; |
|||
import org.thingsboard.server.common.msg.session.FeatureType; |
|||
import org.thingsboard.server.gen.transport.TransportApiProtos; |
|||
|
|||
@Slf4j |
|||
public abstract class AbstractCoapClaimProtoDeviceTest extends AbstractCoapClaimDeviceTest { |
|||
|
|||
@Before |
|||
public void beforeTest() throws Exception { |
|||
processBeforeTest("Test Claim device Proto", CoapDeviceType.DEFAULT, TransportPayloadType.PROTOBUF); |
|||
createCustomerAndUser(); |
|||
} |
|||
|
|||
@After |
|||
public void afterTest() throws Exception { super.afterTest(); } |
|||
|
|||
@Test |
|||
public void testClaimingDevice() throws Exception { |
|||
processTestClaimingDevice(false); |
|||
} |
|||
|
|||
@Test |
|||
public void testClaimingDeviceWithoutSecretAndDuration() throws Exception { |
|||
processTestClaimingDevice(true); |
|||
} |
|||
|
|||
@Override |
|||
protected void processTestClaimingDevice(boolean emptyPayload) throws Exception { |
|||
CoapClient client = getCoapClient(FeatureType.CLAIM); |
|||
byte[] payloadBytes; |
|||
if (emptyPayload) { |
|||
TransportApiProtos.ClaimDevice claimDevice = getClaimDevice(0, emptyPayload); |
|||
payloadBytes = claimDevice.toByteArray(); |
|||
} else { |
|||
TransportApiProtos.ClaimDevice claimDevice = getClaimDevice(60000, emptyPayload); |
|||
payloadBytes = claimDevice.toByteArray(); |
|||
} |
|||
TransportApiProtos.ClaimDevice claimDevice = getClaimDevice(1, emptyPayload); |
|||
byte[] failurePayloadBytes = claimDevice.toByteArray(); |
|||
validateClaimResponse(emptyPayload, client, payloadBytes, failurePayloadBytes); |
|||
} |
|||
|
|||
private TransportApiProtos.ClaimDevice getClaimDevice(long duration, boolean emptyPayload) { |
|||
TransportApiProtos.ClaimDevice.Builder claimDeviceBuilder = TransportApiProtos.ClaimDevice.newBuilder(); |
|||
if (!emptyPayload) { |
|||
claimDeviceBuilder.setSecretKey("value"); |
|||
} |
|||
if (duration > 0) { |
|||
claimDeviceBuilder.setSecretKey("value"); |
|||
claimDeviceBuilder.setDurationMs(duration); |
|||
} else { |
|||
claimDeviceBuilder.setDurationMs(0); |
|||
} |
|||
return claimDeviceBuilder.build(); |
|||
} |
|||
|
|||
|
|||
} |
|||
@ -0,0 +1,23 @@ |
|||
/** |
|||
* 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.coap.claim.sql; |
|||
|
|||
import org.thingsboard.server.transport.coap.claim.AbstractCoapClaimJsonDeviceTest; |
|||
import org.thingsboard.server.dao.service.DaoSqlTest; |
|||
|
|||
@DaoSqlTest |
|||
public class CoapClaimDeviceJsonSqlTest extends AbstractCoapClaimJsonDeviceTest { |
|||
} |
|||
@ -0,0 +1,23 @@ |
|||
/** |
|||
* 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.coap.claim.sql; |
|||
|
|||
import org.thingsboard.server.transport.coap.claim.AbstractCoapClaimProtoDeviceTest; |
|||
import org.thingsboard.server.dao.service.DaoSqlTest; |
|||
|
|||
@DaoSqlTest |
|||
public class CoapClaimDeviceProtoSqlTest extends AbstractCoapClaimProtoDeviceTest { |
|||
} |
|||
@ -0,0 +1,23 @@ |
|||
/** |
|||
* 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.coap.claim.sql; |
|||
|
|||
import org.thingsboard.server.transport.coap.claim.AbstractCoapClaimDeviceTest; |
|||
import org.thingsboard.server.dao.service.DaoSqlTest; |
|||
|
|||
@DaoSqlTest |
|||
public class CoapClaimDeviceSqlTest extends AbstractCoapClaimDeviceTest { |
|||
} |
|||
@ -0,0 +1,195 @@ |
|||
/** |
|||
* 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.coap.provision; |
|||
|
|||
import com.google.gson.JsonObject; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.eclipse.californium.core.CoapClient; |
|||
import org.eclipse.californium.core.CoapResponse; |
|||
import org.eclipse.californium.core.coap.MediaTypeRegistry; |
|||
import org.eclipse.californium.elements.exception.ConnectorException; |
|||
import org.junit.After; |
|||
import org.junit.Assert; |
|||
import org.junit.Test; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.thingsboard.server.transport.coap.AbstractCoapIntegrationTest; |
|||
import org.thingsboard.server.common.data.CoapDeviceType; |
|||
import org.thingsboard.server.common.data.Device; |
|||
import org.thingsboard.server.common.data.DeviceProfileProvisionType; |
|||
import org.thingsboard.server.common.data.TransportPayloadType; |
|||
import org.thingsboard.server.common.data.security.DeviceCredentials; |
|||
import org.thingsboard.server.common.msg.EncryptionUtil; |
|||
import org.thingsboard.server.common.msg.session.FeatureType; |
|||
import org.thingsboard.server.common.transport.util.JsonUtils; |
|||
import org.thingsboard.server.dao.device.DeviceCredentialsService; |
|||
import org.thingsboard.server.dao.device.DeviceService; |
|||
import org.thingsboard.server.dao.device.provision.ProvisionResponseStatus; |
|||
|
|||
import java.io.IOException; |
|||
|
|||
import static org.junit.Assert.assertEquals; |
|||
|
|||
@Slf4j |
|||
public abstract class AbstractCoapProvisionJsonDeviceTest extends AbstractCoapIntegrationTest { |
|||
|
|||
@Autowired |
|||
DeviceCredentialsService deviceCredentialsService; |
|||
|
|||
@Autowired |
|||
DeviceService deviceService; |
|||
|
|||
@After |
|||
public void afterTest() throws Exception { |
|||
super.processAfterTest(); |
|||
} |
|||
|
|||
@Test |
|||
public void testProvisioningDisabledDevice() throws Exception { |
|||
processTestProvisioningDisabledDevice(); |
|||
} |
|||
|
|||
@Test |
|||
public void testProvisioningCheckPreProvisionedDevice() throws Exception { |
|||
processTestProvisioningCheckPreProvisionedDevice(); |
|||
} |
|||
|
|||
@Test |
|||
public void testProvisioningCreateNewDeviceWithoutCredentials() throws Exception { |
|||
processTestProvisioningCreateNewDeviceWithoutCredentials(); |
|||
} |
|||
|
|||
@Test |
|||
public void testProvisioningCreateNewDeviceWithAccessToken() throws Exception { |
|||
processTestProvisioningCreateNewDeviceWithAccessToken(); |
|||
} |
|||
|
|||
@Test |
|||
public void testProvisioningCreateNewDeviceWithCert() throws Exception { |
|||
processTestProvisioningCreateNewDeviceWithCert(); |
|||
} |
|||
|
|||
@Test |
|||
public void testProvisioningWithBadKeyDevice() throws Exception { |
|||
processTestProvisioningWithBadKeyDevice(); |
|||
} |
|||
|
|||
|
|||
private void processTestProvisioningDisabledDevice() throws Exception { |
|||
super.processBeforeTest("Test Provision device", CoapDeviceType.DEFAULT, TransportPayloadType.JSON, null, null, DeviceProfileProvisionType.DISABLED, null, null); |
|||
byte[] result = createCoapClientAndPublish().getPayload(); |
|||
JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject(); |
|||
Assert.assertEquals("Provision data was not found!", response.get("errorMsg").getAsString()); |
|||
Assert.assertEquals(ProvisionResponseStatus.NOT_FOUND.name(), response.get("status").getAsString()); |
|||
} |
|||
|
|||
|
|||
private void processTestProvisioningCreateNewDeviceWithoutCredentials() throws Exception { |
|||
super.processBeforeTest("Test Provision device3", CoapDeviceType.DEFAULT, TransportPayloadType.JSON, null, null, DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES, "testProvisionKey", "testProvisionSecret"); |
|||
byte[] result = createCoapClientAndPublish().getPayload(); |
|||
JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject(); |
|||
|
|||
Device createdDevice = deviceService.findDeviceByTenantIdAndName(savedTenant.getTenantId(), "Test Provision device"); |
|||
|
|||
Assert.assertNotNull(createdDevice); |
|||
|
|||
DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(savedTenant.getTenantId(), createdDevice.getId()); |
|||
|
|||
Assert.assertEquals(deviceCredentials.getCredentialsType().name(), response.get("credentialsType").getAsString()); |
|||
Assert.assertEquals(ProvisionResponseStatus.SUCCESS.name(), response.get("status").getAsString()); |
|||
} |
|||
|
|||
|
|||
private void processTestProvisioningCreateNewDeviceWithAccessToken() throws Exception { |
|||
super.processBeforeTest("Test Provision device3", CoapDeviceType.DEFAULT, TransportPayloadType.JSON, null, null, DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES, "testProvisionKey", "testProvisionSecret"); |
|||
String requestCredentials = ",\"credentialsType\": \"ACCESS_TOKEN\",\"token\": \"test_token\""; |
|||
byte[] result = createCoapClientAndPublish(requestCredentials).getPayload(); |
|||
JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject(); |
|||
|
|||
Device createdDevice = deviceService.findDeviceByTenantIdAndName(savedTenant.getTenantId(), "Test Provision device"); |
|||
|
|||
Assert.assertNotNull(createdDevice); |
|||
|
|||
DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(savedTenant.getTenantId(), createdDevice.getId()); |
|||
|
|||
Assert.assertEquals(deviceCredentials.getCredentialsType().name(), response.get("credentialsType").getAsString()); |
|||
Assert.assertEquals(deviceCredentials.getCredentialsType().name(), "ACCESS_TOKEN"); |
|||
Assert.assertEquals(deviceCredentials.getCredentialsId(), "test_token"); |
|||
Assert.assertEquals(ProvisionResponseStatus.SUCCESS.name(), response.get("status").getAsString()); |
|||
} |
|||
|
|||
|
|||
private void processTestProvisioningCreateNewDeviceWithCert() throws Exception { |
|||
super.processBeforeTest("Test Provision device3", CoapDeviceType.DEFAULT, TransportPayloadType.JSON, null, null, DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES, "testProvisionKey", "testProvisionSecret"); |
|||
String requestCredentials = ",\"credentialsType\": \"X509_CERTIFICATE\",\"hash\": \"testHash\""; |
|||
byte[] result = createCoapClientAndPublish(requestCredentials).getPayload(); |
|||
JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject(); |
|||
|
|||
Device createdDevice = deviceService.findDeviceByTenantIdAndName(savedTenant.getTenantId(), "Test Provision device"); |
|||
|
|||
Assert.assertNotNull(createdDevice); |
|||
|
|||
DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(savedTenant.getTenantId(), createdDevice.getId()); |
|||
|
|||
Assert.assertEquals(deviceCredentials.getCredentialsType().name(), response.get("credentialsType").getAsString()); |
|||
Assert.assertEquals(deviceCredentials.getCredentialsType().name(), "X509_CERTIFICATE"); |
|||
|
|||
String cert = EncryptionUtil.trimNewLines(deviceCredentials.getCredentialsValue()); |
|||
String sha3Hash = EncryptionUtil.getSha3Hash(cert); |
|||
|
|||
Assert.assertEquals(deviceCredentials.getCredentialsId(), sha3Hash); |
|||
|
|||
Assert.assertEquals(deviceCredentials.getCredentialsValue(), "testHash"); |
|||
Assert.assertEquals(ProvisionResponseStatus.SUCCESS.name(), response.get("status").getAsString()); |
|||
} |
|||
|
|||
private void processTestProvisioningCheckPreProvisionedDevice() throws Exception { |
|||
super.processBeforeTest("Test Provision device", CoapDeviceType.DEFAULT, TransportPayloadType.JSON, null, null, DeviceProfileProvisionType.CHECK_PRE_PROVISIONED_DEVICES, "testProvisionKey", "testProvisionSecret"); |
|||
byte[] result = createCoapClientAndPublish().getPayload(); |
|||
JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject(); |
|||
|
|||
DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(savedTenant.getTenantId(), savedDevice.getId()); |
|||
|
|||
Assert.assertEquals(deviceCredentials.getCredentialsType().name(), response.get("credentialsType").getAsString()); |
|||
Assert.assertEquals(ProvisionResponseStatus.SUCCESS.name(), response.get("status").getAsString()); |
|||
} |
|||
|
|||
private void processTestProvisioningWithBadKeyDevice() throws Exception { |
|||
super.processBeforeTest("Test Provision device", CoapDeviceType.DEFAULT, TransportPayloadType.JSON, null, null, DeviceProfileProvisionType.CHECK_PRE_PROVISIONED_DEVICES, "testProvisionKeyOrig", "testProvisionSecret"); |
|||
byte[] result = createCoapClientAndPublish().getPayload(); |
|||
JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject(); |
|||
Assert.assertEquals("Provision data was not found!", response.get("errorMsg").getAsString()); |
|||
Assert.assertEquals(ProvisionResponseStatus.NOT_FOUND.name(), response.get("status").getAsString()); |
|||
} |
|||
|
|||
private CoapResponse createCoapClientAndPublish() throws Exception { |
|||
return createCoapClientAndPublish(""); |
|||
} |
|||
|
|||
private CoapResponse createCoapClientAndPublish(String deviceCredentials) throws Exception { |
|||
String provisionRequestMsg = createTestProvisionMessage(deviceCredentials); |
|||
CoapClient client = getCoapClient(FeatureType.PROVISION); |
|||
return postProvision(client, provisionRequestMsg.getBytes()); |
|||
} |
|||
|
|||
|
|||
private CoapResponse postProvision(CoapClient client, byte[] payload) throws IOException, ConnectorException { |
|||
return client.setTimeout((long) 60000).post(payload, MediaTypeRegistry.APPLICATION_JSON); |
|||
} |
|||
|
|||
private String createTestProvisionMessage(String deviceCredentials) { |
|||
return "{\"deviceName\":\"Test Provision device\",\"provisionDeviceKey\":\"testProvisionKey\", \"provisionDeviceSecret\":\"testProvisionSecret\"" + deviceCredentials + "}"; |
|||
} |
|||
} |
|||
@ -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.coap.provision; |
|||
|
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.eclipse.californium.core.CoapClient; |
|||
import org.eclipse.californium.core.CoapResponse; |
|||
import org.eclipse.californium.core.coap.MediaTypeRegistry; |
|||
import org.eclipse.californium.elements.exception.ConnectorException; |
|||
import org.junit.After; |
|||
import org.junit.Assert; |
|||
import org.junit.Test; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.thingsboard.server.transport.coap.AbstractCoapIntegrationTest; |
|||
import org.thingsboard.server.common.data.CoapDeviceType; |
|||
import org.thingsboard.server.common.data.Device; |
|||
import org.thingsboard.server.common.data.DeviceProfileProvisionType; |
|||
import org.thingsboard.server.common.data.TransportPayloadType; |
|||
import org.thingsboard.server.common.data.security.DeviceCredentials; |
|||
import org.thingsboard.server.common.data.security.DeviceCredentialsType; |
|||
import org.thingsboard.server.common.msg.EncryptionUtil; |
|||
import org.thingsboard.server.common.msg.session.FeatureType; |
|||
import org.thingsboard.server.dao.device.DeviceCredentialsService; |
|||
import org.thingsboard.server.dao.device.DeviceService; |
|||
import org.thingsboard.server.dao.device.provision.ProvisionResponseStatus; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.CredentialsDataProto; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.CredentialsType; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceCredentialsMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceRequestMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceResponseMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceTokenRequestMsg; |
|||
import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceX509CertRequestMsg; |
|||
|
|||
import java.io.IOException; |
|||
|
|||
@Slf4j |
|||
public abstract class AbstractCoapProvisionProtoDeviceTest extends AbstractCoapIntegrationTest { |
|||
|
|||
@Autowired |
|||
DeviceCredentialsService deviceCredentialsService; |
|||
|
|||
@Autowired |
|||
DeviceService deviceService; |
|||
|
|||
@After |
|||
public void afterTest() throws Exception { |
|||
super.processAfterTest(); |
|||
} |
|||
|
|||
@Test |
|||
public void testProvisioningDisabledDevice() throws Exception { |
|||
processTestProvisioningDisabledDevice(); |
|||
} |
|||
|
|||
@Test |
|||
public void testProvisioningCheckPreProvisionedDevice() throws Exception { |
|||
processTestProvisioningCheckPreProvisionedDevice(); |
|||
} |
|||
|
|||
@Test |
|||
public void testProvisioningCreateNewDeviceWithoutCredentials() throws Exception { |
|||
processTestProvisioningCreateNewDeviceWithoutCredentials(); |
|||
} |
|||
|
|||
@Test |
|||
public void testProvisioningCreateNewDeviceWithAccessToken() throws Exception { |
|||
processTestProvisioningCreateNewDeviceWithAccessToken(); |
|||
} |
|||
|
|||
@Test |
|||
public void testProvisioningCreateNewDeviceWithCert() throws Exception { |
|||
processTestProvisioningCreateNewDeviceWithCert(); |
|||
} |
|||
|
|||
@Test |
|||
public void testProvisioningWithBadKeyDevice() throws Exception { |
|||
processTestProvisioningWithBadKeyDevice(); |
|||
} |
|||
|
|||
|
|||
private void processTestProvisioningDisabledDevice() throws Exception { |
|||
super.processBeforeTest("Test Provision device", CoapDeviceType.DEFAULT, TransportPayloadType.PROTOBUF, null, null, DeviceProfileProvisionType.DISABLED, null, null); |
|||
ProvisionDeviceResponseMsg result = ProvisionDeviceResponseMsg.parseFrom(createCoapClientAndPublish().getPayload()); |
|||
Assert.assertNotNull(result); |
|||
Assert.assertEquals(ProvisionResponseStatus.NOT_FOUND.name(), result.getStatus().toString()); |
|||
} |
|||
|
|||
private void processTestProvisioningCreateNewDeviceWithoutCredentials() throws Exception { |
|||
super.processBeforeTest("Test Provision device3", CoapDeviceType.DEFAULT, TransportPayloadType.PROTOBUF, null, null, DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES, "testProvisionKey", "testProvisionSecret"); |
|||
ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createCoapClientAndPublish().getPayload()); |
|||
|
|||
Device createdDevice = deviceService.findDeviceByTenantIdAndName(savedTenant.getTenantId(), "Test Provision device"); |
|||
|
|||
Assert.assertNotNull(createdDevice); |
|||
|
|||
DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(savedTenant.getTenantId(), createdDevice.getId()); |
|||
|
|||
Assert.assertEquals(deviceCredentials.getCredentialsType().name(), response.getCredentialsType().toString()); |
|||
Assert.assertEquals(ProvisionResponseStatus.SUCCESS.name(), response.getStatus().toString()); |
|||
} |
|||
|
|||
private void processTestProvisioningCreateNewDeviceWithAccessToken() throws Exception { |
|||
super.processBeforeTest("Test Provision device3", CoapDeviceType.DEFAULT, TransportPayloadType.PROTOBUF, null, null, DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES, "testProvisionKey", "testProvisionSecret"); |
|||
CredentialsDataProto requestCredentials = CredentialsDataProto.newBuilder().setValidateDeviceTokenRequestMsg(ValidateDeviceTokenRequestMsg.newBuilder().setToken("test_token").build()).build(); |
|||
|
|||
ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createCoapClientAndPublish(createTestsProvisionMessage(CredentialsType.ACCESS_TOKEN, requestCredentials)).getPayload()); |
|||
|
|||
Device createdDevice = deviceService.findDeviceByTenantIdAndName(savedTenant.getTenantId(), "Test Provision device"); |
|||
|
|||
Assert.assertNotNull(createdDevice); |
|||
|
|||
DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(savedTenant.getTenantId(), createdDevice.getId()); |
|||
|
|||
Assert.assertEquals(deviceCredentials.getCredentialsType().name(), response.getCredentialsType().toString()); |
|||
Assert.assertEquals(deviceCredentials.getCredentialsType(), DeviceCredentialsType.ACCESS_TOKEN); |
|||
Assert.assertEquals(deviceCredentials.getCredentialsId(), "test_token"); |
|||
Assert.assertEquals(ProvisionResponseStatus.SUCCESS.name(), response.getStatus().toString()); |
|||
} |
|||
|
|||
private void processTestProvisioningCreateNewDeviceWithCert() throws Exception { |
|||
super.processBeforeTest("Test Provision device3", CoapDeviceType.DEFAULT, TransportPayloadType.PROTOBUF, null, null, DeviceProfileProvisionType.ALLOW_CREATE_NEW_DEVICES, "testProvisionKey", "testProvisionSecret"); |
|||
CredentialsDataProto requestCredentials = CredentialsDataProto.newBuilder().setValidateDeviceX509CertRequestMsg(ValidateDeviceX509CertRequestMsg.newBuilder().setHash("testHash").build()).build(); |
|||
|
|||
ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createCoapClientAndPublish(createTestsProvisionMessage(CredentialsType.X509_CERTIFICATE, requestCredentials)).getPayload()); |
|||
|
|||
Device createdDevice = deviceService.findDeviceByTenantIdAndName(savedTenant.getTenantId(), "Test Provision device"); |
|||
|
|||
Assert.assertNotNull(createdDevice); |
|||
|
|||
DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(savedTenant.getTenantId(), createdDevice.getId()); |
|||
|
|||
Assert.assertEquals(deviceCredentials.getCredentialsType().name(), response.getCredentialsType().toString()); |
|||
Assert.assertEquals(deviceCredentials.getCredentialsType(), DeviceCredentialsType.X509_CERTIFICATE); |
|||
|
|||
String cert = EncryptionUtil.trimNewLines(deviceCredentials.getCredentialsValue()); |
|||
String sha3Hash = EncryptionUtil.getSha3Hash(cert); |
|||
|
|||
Assert.assertEquals(deviceCredentials.getCredentialsId(), sha3Hash); |
|||
|
|||
Assert.assertEquals(deviceCredentials.getCredentialsValue(), "testHash"); |
|||
Assert.assertEquals(ProvisionResponseStatus.SUCCESS.name(), response.getStatus().toString()); |
|||
} |
|||
|
|||
private void processTestProvisioningCheckPreProvisionedDevice() throws Exception { |
|||
super.processBeforeTest("Test Provision device", CoapDeviceType.DEFAULT, TransportPayloadType.PROTOBUF, null, null, DeviceProfileProvisionType.CHECK_PRE_PROVISIONED_DEVICES, "testProvisionKey", "testProvisionSecret"); |
|||
ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createCoapClientAndPublish().getPayload()); |
|||
|
|||
DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(savedTenant.getTenantId(), savedDevice.getId()); |
|||
|
|||
Assert.assertEquals(deviceCredentials.getCredentialsType().name(), response.getCredentialsType().toString()); |
|||
Assert.assertEquals(ProvisionResponseStatus.SUCCESS.name(), response.getStatus().toString()); |
|||
} |
|||
|
|||
private void processTestProvisioningWithBadKeyDevice() throws Exception { |
|||
super.processBeforeTest("Test Provision device", CoapDeviceType.DEFAULT, TransportPayloadType.PROTOBUF, null, null, DeviceProfileProvisionType.CHECK_PRE_PROVISIONED_DEVICES, "testProvisionKeyOrig", "testProvisionSecret"); |
|||
ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createCoapClientAndPublish().getPayload()); |
|||
Assert.assertEquals(ProvisionResponseStatus.NOT_FOUND.name(), response.getStatus().toString()); |
|||
} |
|||
|
|||
private CoapResponse createCoapClientAndPublish() throws Exception { |
|||
byte[] provisionRequestMsg = createTestProvisionMessage(); |
|||
return createCoapClientAndPublish(provisionRequestMsg); |
|||
} |
|||
|
|||
private CoapResponse createCoapClientAndPublish(byte[] provisionRequestMsg) throws Exception { |
|||
CoapClient client = getCoapClient(FeatureType.PROVISION); |
|||
return postProvision(client, provisionRequestMsg); |
|||
} |
|||
|
|||
private CoapResponse postProvision(CoapClient client, byte[] payload) throws IOException, ConnectorException { |
|||
return client.setTimeout((long) 60000).post(payload, MediaTypeRegistry.APPLICATION_JSON); |
|||
} |
|||
|
|||
private byte[] createTestsProvisionMessage(CredentialsType credentialsType, CredentialsDataProto credentialsData) throws Exception { |
|||
return ProvisionDeviceRequestMsg.newBuilder() |
|||
.setDeviceName("Test Provision device") |
|||
.setCredentialsType(credentialsType != null ? credentialsType : CredentialsType.ACCESS_TOKEN) |
|||
.setCredentialsDataProto(credentialsData != null ? credentialsData: CredentialsDataProto.newBuilder().build()) |
|||
.setProvisionDeviceCredentialsMsg( |
|||
ProvisionDeviceCredentialsMsg.newBuilder() |
|||
.setProvisionDeviceKey("testProvisionKey") |
|||
.setProvisionDeviceSecret("testProvisionSecret") |
|||
).build() |
|||
.toByteArray(); |
|||
} |
|||
|
|||
|
|||
private byte[] createTestProvisionMessage() throws Exception { |
|||
return createTestsProvisionMessage(null, null); |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,23 @@ |
|||
/** |
|||
* 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.coap.provision.sql; |
|||
|
|||
import org.thingsboard.server.transport.coap.provision.AbstractCoapProvisionJsonDeviceTest; |
|||
import org.thingsboard.server.dao.service.DaoSqlTest; |
|||
|
|||
@DaoSqlTest |
|||
public class CoapProvisionDeviceJsonSqlTest extends AbstractCoapProvisionJsonDeviceTest { |
|||
} |
|||
@ -0,0 +1,23 @@ |
|||
/** |
|||
* 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.coap.provision.sql; |
|||
|
|||
import org.thingsboard.server.transport.coap.provision.AbstractCoapProvisionProtoDeviceTest; |
|||
import org.thingsboard.server.dao.service.DaoSqlTest; |
|||
|
|||
@DaoSqlTest |
|||
public class CoapProvisionDeviceProtoSqlTest extends AbstractCoapProvisionProtoDeviceTest { |
|||
} |
|||
@ -0,0 +1,89 @@ |
|||
/** |
|||
* 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.coap.rpc; |
|||
|
|||
import com.datastax.oss.driver.api.core.uuid.Uuids; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.junit.After; |
|||
import org.junit.Assert; |
|||
import org.junit.Before; |
|||
import org.junit.Test; |
|||
import org.thingsboard.server.service.security.AccessValidator; |
|||
|
|||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; |
|||
|
|||
@Slf4j |
|||
public abstract class AbstractCoapServerSideRpcDefaultIntegrationTest extends AbstractCoapServerSideRpcIntegrationTest { |
|||
|
|||
@Before |
|||
public void beforeTest() throws Exception { |
|||
processBeforeTest("RPC test device", null, null); |
|||
} |
|||
|
|||
@After |
|||
public void afterTest() throws Exception { |
|||
super.processAfterTest(); |
|||
} |
|||
|
|||
@Test |
|||
public void testServerCoapOneWayRpcDeviceOffline() throws Exception { |
|||
String setGpioRequest = "{\"method\":\"setGpio\",\"params\":{\"pin\": \"24\",\"value\": 1},\"timeout\": 6000}"; |
|||
String deviceId = savedDevice.getId().getId().toString(); |
|||
|
|||
doPostAsync("/api/plugins/rpc/oneway/" + deviceId, setGpioRequest, String.class, status().is(409), |
|||
asyncContextTimeoutToUseRpcPlugin); |
|||
} |
|||
|
|||
@Test |
|||
public void testServerCoapOneWayRpcDeviceDoesNotExist() throws Exception { |
|||
String setGpioRequest = "{\"method\":\"setGpio\",\"params\":{\"pin\": \"25\",\"value\": 1}}"; |
|||
String nonExistentDeviceId = Uuids.timeBased().toString(); |
|||
|
|||
String result = doPostAsync("/api/plugins/rpc/oneway/" + nonExistentDeviceId, setGpioRequest, String.class, |
|||
status().isNotFound()); |
|||
Assert.assertEquals(AccessValidator.DEVICE_WITH_REQUESTED_ID_NOT_FOUND, result); |
|||
} |
|||
|
|||
@Test |
|||
public void testServerCoapTwoWayRpcDeviceOffline() throws Exception { |
|||
String setGpioRequest = "{\"method\":\"setGpio\",\"params\":{\"pin\": \"27\",\"value\": 1},\"timeout\": 6000}"; |
|||
String deviceId = savedDevice.getId().getId().toString(); |
|||
|
|||
doPostAsync("/api/plugins/rpc/twoway/" + deviceId, setGpioRequest, String.class, status().is(409), |
|||
asyncContextTimeoutToUseRpcPlugin); |
|||
} |
|||
|
|||
@Test |
|||
public void testServerCoapTwoWayRpcDeviceDoesNotExist() throws Exception { |
|||
String setGpioRequest = "{\"method\":\"setGpio\",\"params\":{\"pin\": \"28\",\"value\": 1}}"; |
|||
String nonExistentDeviceId = Uuids.timeBased().toString(); |
|||
|
|||
String result = doPostAsync("/api/plugins/rpc/twoway/" + nonExistentDeviceId, setGpioRequest, String.class, |
|||
status().isNotFound()); |
|||
Assert.assertEquals(AccessValidator.DEVICE_WITH_REQUESTED_ID_NOT_FOUND, result); |
|||
} |
|||
|
|||
@Test |
|||
public void testServerCoapOneWayRpc() throws Exception { |
|||
processOneWayRpcTest(); |
|||
} |
|||
|
|||
@Test |
|||
public void testServerCoapTwoWayRpc() throws Exception { |
|||
processTwoWayRpcTest(); |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,165 @@ |
|||
/** |
|||
* 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.coap.rpc; |
|||
|
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.apache.commons.lang3.StringUtils; |
|||
import org.eclipse.californium.core.CoapClient; |
|||
import org.eclipse.californium.core.CoapHandler; |
|||
import org.eclipse.californium.core.CoapObserveRelation; |
|||
import org.eclipse.californium.core.CoapResponse; |
|||
import org.eclipse.californium.core.coap.CoAP; |
|||
import org.eclipse.californium.core.coap.MediaTypeRegistry; |
|||
import org.eclipse.californium.core.coap.Request; |
|||
import org.junit.Assert; |
|||
import org.thingsboard.server.transport.coap.AbstractCoapIntegrationTest; |
|||
import org.thingsboard.server.common.data.CoapDeviceType; |
|||
import org.thingsboard.server.common.data.TransportPayloadType; |
|||
import org.thingsboard.server.common.msg.session.FeatureType; |
|||
|
|||
import java.util.concurrent.CountDownLatch; |
|||
import java.util.concurrent.TimeUnit; |
|||
|
|||
import static org.junit.Assert.assertEquals; |
|||
import static org.junit.Assert.assertNotNull; |
|||
import static org.junit.Assert.assertTrue; |
|||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; |
|||
|
|||
@Slf4j |
|||
public abstract class AbstractCoapServerSideRpcIntegrationTest extends AbstractCoapIntegrationTest { |
|||
|
|||
protected static final String DEVICE_RESPONSE = "{\"value1\":\"A\",\"value2\":\"B\"}"; |
|||
|
|||
protected Long asyncContextTimeoutToUseRpcPlugin; |
|||
|
|||
protected void processBeforeTest(String deviceName, CoapDeviceType coapDeviceType, TransportPayloadType payloadType) throws Exception { |
|||
super.processBeforeTest(deviceName, coapDeviceType, payloadType); |
|||
asyncContextTimeoutToUseRpcPlugin = 10000L; |
|||
} |
|||
|
|||
protected void processOneWayRpcTest() throws Exception { |
|||
CoapClient client = getCoapClient(FeatureType.RPC); |
|||
client.useCONs(); |
|||
|
|||
CountDownLatch latch = new CountDownLatch(1); |
|||
TestCoapCallback testCoapCallback = new TestCoapCallback(client, latch, true); |
|||
|
|||
Request request = Request.newGet().setObserve(); |
|||
CoapObserveRelation observeRelation = client.observe(request, testCoapCallback); |
|||
|
|||
String setGpioRequest = "{\"method\":\"setGpio\",\"params\":{\"pin\": \"23\",\"value\": 1}}"; |
|||
String deviceId = savedDevice.getId().getId().toString(); |
|||
String result = doPostAsync("/api/plugins/rpc/oneway/" + deviceId, setGpioRequest, String.class, status().isOk()); |
|||
Assert.assertTrue(StringUtils.isEmpty(result)); |
|||
latch.await(3, TimeUnit.SECONDS); |
|||
assertEquals(0, testCoapCallback.getObserve().intValue()); |
|||
observeRelation.proactiveCancel(); |
|||
assertTrue(observeRelation.isCanceled()); |
|||
} |
|||
|
|||
protected void processTwoWayRpcTest() throws Exception { |
|||
CoapClient client = getCoapClient(FeatureType.RPC); |
|||
client.useCONs(); |
|||
|
|||
CountDownLatch latch = new CountDownLatch(1); |
|||
TestCoapCallback testCoapCallback = new TestCoapCallback(client, latch, false); |
|||
|
|||
Request request = Request.newGet().setObserve(); |
|||
request.setType(CoAP.Type.CON); |
|||
CoapObserveRelation observeRelation = client.observe(request, testCoapCallback); |
|||
|
|||
String setGpioRequest = "{\"method\":\"setGpio\",\"params\":{\"pin\": \"26\",\"value\": 1}}"; |
|||
String deviceId = savedDevice.getId().getId().toString(); |
|||
|
|||
String expected = "{\"value1\":\"A\",\"value2\":\"B\"}"; |
|||
|
|||
String result = doPostAsync("/api/plugins/rpc/twoway/" + deviceId, setGpioRequest, String.class, status().isOk()); |
|||
latch.await(3, TimeUnit.SECONDS); |
|||
|
|||
assertEquals(expected, result); |
|||
assertEquals(0, testCoapCallback.getObserve().intValue()); |
|||
observeRelation.proactiveCancel(); |
|||
assertTrue(observeRelation.isCanceled()); |
|||
|
|||
// // TODO: 3/11/21 Fix test to validate next RPC
|
|||
// latch = new CountDownLatch(1);
|
|||
//
|
|||
// result = doPostAsync("/api/plugins/rpc/twoway/" + deviceId, setGpioRequest, String.class, status().isOk());
|
|||
// latch.await(3, TimeUnit.SECONDS);
|
|||
//
|
|||
// assertEquals(expected, result);
|
|||
// assertEquals(1, testCoapCallback.getObserve().intValue());
|
|||
} |
|||
|
|||
protected void processOnLoadResponse(CoapResponse response, CoapClient client, Integer observe, CountDownLatch latch) { |
|||
client.setURI(getRpcResponseFeatureTokenUrl(accessToken, observe)); |
|||
client.post(new CoapHandler() { |
|||
@Override |
|||
public void onLoad(CoapResponse response) { |
|||
log.warn("Command Response Ack: {}, {}", response.getCode(), response.getResponseText()); |
|||
latch.countDown(); |
|||
} |
|||
|
|||
@Override |
|||
public void onError() { |
|||
log.warn("Command Response Ack Error, No connect"); |
|||
} |
|||
}, DEVICE_RESPONSE, MediaTypeRegistry.APPLICATION_JSON); |
|||
} |
|||
|
|||
protected String getRpcResponseFeatureTokenUrl(String token, int requestId) { |
|||
return COAP_BASE_URL + token + "/" + FeatureType.RPC.name().toLowerCase() + "/" + requestId; |
|||
} |
|||
|
|||
private class TestCoapCallback implements CoapHandler { |
|||
|
|||
private final CoapClient client; |
|||
private final CountDownLatch latch; |
|||
private final boolean isOneWayRpc; |
|||
|
|||
public Integer getObserve() { |
|||
return observe; |
|||
} |
|||
|
|||
private Integer observe; |
|||
|
|||
private TestCoapCallback(CoapClient client, CountDownLatch latch, boolean isOneWayRpc) { |
|||
this.client = client; |
|||
this.latch = latch; |
|||
this.isOneWayRpc = isOneWayRpc; |
|||
} |
|||
|
|||
@Override |
|||
public void onLoad(CoapResponse response) { |
|||
log.warn("coap response: {}, {}", response, response.getCode()); |
|||
assertNotNull(response.getPayload()); |
|||
assertEquals(response.getCode(), CoAP.ResponseCode.CONTENT); |
|||
observe = response.getOptions().getObserve(); |
|||
if (!isOneWayRpc) { |
|||
processOnLoadResponse(response, client, observe, latch); |
|||
} else { |
|||
latch.countDown(); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public void onError() { |
|||
log.warn("Command Response Ack Error, No connect"); |
|||
} |
|||
|
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,48 @@ |
|||
/** |
|||
* 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.coap.rpc; |
|||
|
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.junit.After; |
|||
import org.junit.Before; |
|||
import org.junit.Test; |
|||
import org.thingsboard.server.common.data.CoapDeviceType; |
|||
import org.thingsboard.server.common.data.TransportPayloadType; |
|||
|
|||
@Slf4j |
|||
public abstract class AbstractCoapServerSideRpcJsonIntegrationTest extends AbstractCoapServerSideRpcIntegrationTest { |
|||
|
|||
@Before |
|||
public void beforeTest() throws Exception { |
|||
processBeforeTest("RPC test device", CoapDeviceType.DEFAULT, TransportPayloadType.JSON); |
|||
} |
|||
|
|||
@After |
|||
public void afterTest() throws Exception { |
|||
super.processAfterTest(); |
|||
} |
|||
|
|||
@Test |
|||
public void testServerMqttOneWayRpc() throws Exception { |
|||
processOneWayRpcTest(); |
|||
} |
|||
|
|||
@Test |
|||
public void testServerMqttTwoWayRpc() throws Exception { |
|||
processTwoWayRpcTest(); |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,75 @@ |
|||
/** |
|||
* 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.coap.rpc; |
|||
|
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.eclipse.californium.core.CoapClient; |
|||
import org.eclipse.californium.core.CoapHandler; |
|||
import org.eclipse.californium.core.CoapResponse; |
|||
import org.eclipse.californium.core.coap.MediaTypeRegistry; |
|||
import org.junit.After; |
|||
import org.junit.Before; |
|||
import org.junit.Test; |
|||
import org.thingsboard.server.common.data.CoapDeviceType; |
|||
import org.thingsboard.server.common.data.TransportPayloadType; |
|||
import org.thingsboard.server.gen.transport.TransportProtos; |
|||
|
|||
import java.util.concurrent.CountDownLatch; |
|||
|
|||
@Slf4j |
|||
public abstract class AbstractCoapServerSideRpcProtoIntegrationTest extends AbstractCoapServerSideRpcIntegrationTest { |
|||
|
|||
@Before |
|||
public void beforeTest() throws Exception { |
|||
processBeforeTest("RPC test device", CoapDeviceType.DEFAULT, TransportPayloadType.PROTOBUF); |
|||
} |
|||
|
|||
@After |
|||
public void afterTest() throws Exception { |
|||
super.processAfterTest(); |
|||
} |
|||
|
|||
@Test |
|||
public void testServerMqttOneWayRpc() throws Exception { |
|||
processOneWayRpcTest(); |
|||
} |
|||
|
|||
@Test |
|||
public void testServerMqttTwoWayRpc() throws Exception { |
|||
processTwoWayRpcTest(); |
|||
} |
|||
|
|||
@Override |
|||
protected void processOnLoadResponse(CoapResponse response, CoapClient client, Integer observe, CountDownLatch latch) { |
|||
client.setURI(getRpcResponseFeatureTokenUrl(accessToken, observe)); |
|||
TransportProtos.ToDeviceRpcResponseMsg toDeviceRpcResponseMsg = TransportProtos.ToDeviceRpcResponseMsg.newBuilder() |
|||
.setPayload(DEVICE_RESPONSE) |
|||
.setRequestId(observe) |
|||
.build(); |
|||
client.post(new CoapHandler() { |
|||
@Override |
|||
public void onLoad(CoapResponse response) { |
|||
log.warn("Command Response Ack: {}, {}", response.getCode(), response.getResponseText()); |
|||
latch.countDown(); |
|||
} |
|||
|
|||
@Override |
|||
public void onError() { |
|||
log.warn("Command Response Ack Error, No connect"); |
|||
} |
|||
}, toDeviceRpcResponseMsg.toByteArray(), MediaTypeRegistry.APPLICATION_JSON); |
|||
} |
|||
} |
|||
@ -0,0 +1,23 @@ |
|||
/** |
|||
* 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.coap.rpc.sql; |
|||
|
|||
import org.thingsboard.server.transport.coap.rpc.AbstractCoapServerSideRpcJsonIntegrationTest; |
|||
import org.thingsboard.server.dao.service.DaoSqlTest; |
|||
|
|||
@DaoSqlTest |
|||
public class CoapServerSideRpcJsonSqlIntegrationTest extends AbstractCoapServerSideRpcJsonIntegrationTest { |
|||
} |
|||
@ -0,0 +1,24 @@ |
|||
/** |
|||
* 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.coap.rpc.sql; |
|||
|
|||
import org.thingsboard.server.transport.coap.rpc.AbstractCoapServerSideRpcProtoIntegrationTest; |
|||
import org.thingsboard.server.dao.service.DaoSqlTest; |
|||
|
|||
|
|||
@DaoSqlTest |
|||
public class CoapServerSideRpcProtoSqlIntegrationTest extends AbstractCoapServerSideRpcProtoIntegrationTest { |
|||
} |
|||
@ -0,0 +1,23 @@ |
|||
/** |
|||
* 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.coap.rpc.sql; |
|||
|
|||
import org.thingsboard.server.transport.coap.rpc.AbstractCoapServerSideRpcDefaultIntegrationTest; |
|||
import org.thingsboard.server.dao.service.DaoSqlTest; |
|||
|
|||
@DaoSqlTest |
|||
public class CoapServerSideRpcSqlIntegrationTest extends AbstractCoapServerSideRpcDefaultIntegrationTest { |
|||
} |
|||
@ -0,0 +1,145 @@ |
|||
/** |
|||
* 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.coap.telemetry.attributes; |
|||
|
|||
import com.fasterxml.jackson.core.JsonProcessingException; |
|||
import com.fasterxml.jackson.core.type.TypeReference; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.eclipse.californium.core.CoapClient; |
|||
import org.eclipse.californium.core.CoapResponse; |
|||
import org.eclipse.californium.core.coap.CoAP; |
|||
import org.eclipse.californium.core.coap.MediaTypeRegistry; |
|||
import org.eclipse.californium.elements.exception.ConnectorException; |
|||
import org.junit.After; |
|||
import org.junit.Before; |
|||
import org.junit.Test; |
|||
import org.thingsboard.server.transport.coap.AbstractCoapIntegrationTest; |
|||
import org.thingsboard.server.common.data.id.DeviceId; |
|||
import org.thingsboard.server.common.msg.session.FeatureType; |
|||
|
|||
import java.io.IOException; |
|||
import java.util.Arrays; |
|||
import java.util.HashSet; |
|||
import java.util.LinkedHashMap; |
|||
import java.util.List; |
|||
import java.util.Map; |
|||
import java.util.Set; |
|||
|
|||
import static org.junit.Assert.assertEquals; |
|||
import static org.junit.Assert.assertNotNull; |
|||
import static org.junit.Assert.assertTrue; |
|||
|
|||
@Slf4j |
|||
public abstract class AbstractCoapAttributesIntegrationTest extends AbstractCoapIntegrationTest { |
|||
|
|||
private static final String PAYLOAD_VALUES_STR = "{\"key1\":\"value1\", \"key2\":true, \"key3\": 3.0, \"key4\": 4," + |
|||
" \"key5\": {\"someNumber\": 42, \"someArray\": [1,2,3], \"someNestedObject\": {\"key\": \"value\"}}}"; |
|||
|
|||
@Before |
|||
public void beforeTest() throws Exception { |
|||
processBeforeTest("Test Post Attributes device", null, null); |
|||
} |
|||
|
|||
@After |
|||
public void afterTest() throws Exception { |
|||
processAfterTest(); |
|||
} |
|||
|
|||
@Test |
|||
public void testPushAttributes() throws Exception { |
|||
List<String> expectedKeys = Arrays.asList("key1", "key2", "key3", "key4", "key5"); |
|||
processAttributesTest(expectedKeys, PAYLOAD_VALUES_STR.getBytes()); |
|||
} |
|||
|
|||
protected void processAttributesTest(List<String> expectedKeys, byte[] payload) throws Exception { |
|||
log.warn("[testPushAttributes] Device: {}, Transport type: {}", savedDevice.getName(), savedDevice.getType()); |
|||
CoapClient client = getCoapClient(FeatureType.ATTRIBUTES); |
|||
|
|||
postAttributes(client, payload); |
|||
|
|||
DeviceId deviceId = savedDevice.getId(); |
|||
|
|||
long start = System.currentTimeMillis(); |
|||
long end = System.currentTimeMillis() + 5000; |
|||
|
|||
List<String> actualKeys = null; |
|||
while (start <= end) { |
|||
actualKeys = doGetAsyncTyped("/api/plugins/telemetry/DEVICE/" + deviceId + "/keys/attributes/CLIENT_SCOPE", new TypeReference<>() {}); |
|||
if (actualKeys.size() == expectedKeys.size()) { |
|||
break; |
|||
} |
|||
Thread.sleep(100); |
|||
start += 100; |
|||
} |
|||
assertNotNull(actualKeys); |
|||
|
|||
Set<String> actualKeySet = new HashSet<>(actualKeys); |
|||
|
|||
Set<String> expectedKeySet = new HashSet<>(expectedKeys); |
|||
|
|||
assertEquals(expectedKeySet, actualKeySet); |
|||
|
|||
String getAttributesValuesUrl = getAttributesValuesUrl(deviceId, actualKeySet); |
|||
List<Map<String, Object>> values = doGetAsyncTyped(getAttributesValuesUrl, new TypeReference<>() {}); |
|||
assertAttributesValues(values, expectedKeySet); |
|||
String deleteAttributesUrl = "/api/plugins/telemetry/DEVICE/" + deviceId + "/CLIENT_SCOPE?keys=" + String.join(",", actualKeySet); |
|||
doDelete(deleteAttributesUrl); |
|||
} |
|||
|
|||
private void postAttributes(CoapClient client, byte[] payload) throws IOException, ConnectorException { |
|||
if (payload == null) { |
|||
payload = PAYLOAD_VALUES_STR.getBytes(); |
|||
} |
|||
CoapResponse coapResponse = client.setTimeout((long) 60000).post(payload, MediaTypeRegistry.APPLICATION_JSON); |
|||
assertEquals(CoAP.ResponseCode.CREATED, coapResponse.getCode()); |
|||
} |
|||
|
|||
@SuppressWarnings("unchecked") |
|||
protected void assertAttributesValues(List<Map<String, Object>> deviceValues, Set<String> expectedKeySet) throws JsonProcessingException { |
|||
for (Map<String, Object> map : deviceValues) { |
|||
String key = (String) map.get("key"); |
|||
Object value = map.get("value"); |
|||
assertTrue(expectedKeySet.contains(key)); |
|||
switch (key) { |
|||
case "key1": |
|||
assertEquals("value1", value); |
|||
break; |
|||
case "key2": |
|||
assertEquals(true, value); |
|||
break; |
|||
case "key3": |
|||
assertEquals(3.0, value); |
|||
break; |
|||
case "key4": |
|||
assertEquals(4, value); |
|||
break; |
|||
case "key5": |
|||
assertNotNull(value); |
|||
assertEquals(3, ((LinkedHashMap) value).size()); |
|||
assertEquals(42, ((LinkedHashMap) value).get("someNumber")); |
|||
assertEquals(Arrays.asList(1, 2, 3), ((LinkedHashMap) value).get("someArray")); |
|||
LinkedHashMap<String, String> someNestedObject = (LinkedHashMap) ((LinkedHashMap) value).get("someNestedObject"); |
|||
assertEquals("value", someNestedObject.get("key")); |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
|
|||
private String getAttributesValuesUrl(DeviceId deviceId, Set<String> actualKeySet) { |
|||
return "/api/plugins/telemetry/DEVICE/" + deviceId + "/values/attributes/CLIENT_SCOPE?keys=" + String.join(",", actualKeySet); |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,42 @@ |
|||
/** |
|||
* 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.coap.telemetry.attributes; |
|||
|
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.junit.After; |
|||
import org.junit.Before; |
|||
import org.junit.Test; |
|||
import org.thingsboard.server.common.data.CoapDeviceType; |
|||
import org.thingsboard.server.common.data.TransportPayloadType; |
|||
|
|||
@Slf4j |
|||
public abstract class AbstractCoapAttributesJsonIntegrationTest extends AbstractCoapAttributesIntegrationTest { |
|||
|
|||
@Before |
|||
public void beforeTest() throws Exception { |
|||
processBeforeTest("Test Post Attributes device Json", CoapDeviceType.DEFAULT, TransportPayloadType.JSON); |
|||
} |
|||
|
|||
@After |
|||
public void afterTest() throws Exception { |
|||
processAfterTest(); |
|||
} |
|||
|
|||
@Test |
|||
public void testPushAttributes() throws Exception { |
|||
super.testPushAttributes(); |
|||
} |
|||
} |
|||
@ -0,0 +1,93 @@ |
|||
/** |
|||
* 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.coap.telemetry.attributes; |
|||
|
|||
import com.github.os72.protobuf.dynamic.DynamicSchema; |
|||
import com.google.protobuf.Descriptors; |
|||
import com.google.protobuf.DynamicMessage; |
|||
import com.squareup.wire.schema.internal.parser.ProtoFileElement; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.junit.After; |
|||
import org.junit.Test; |
|||
import org.thingsboard.server.common.data.CoapDeviceType; |
|||
import org.thingsboard.server.common.data.TransportPayloadType; |
|||
import org.thingsboard.server.common.data.device.profile.CoapDeviceProfileTransportConfiguration; |
|||
import org.thingsboard.server.common.data.device.profile.CoapDeviceTypeConfiguration; |
|||
import org.thingsboard.server.common.data.device.profile.DefaultCoapDeviceTypeConfiguration; |
|||
import org.thingsboard.server.common.data.device.profile.DeviceProfileTransportConfiguration; |
|||
import org.thingsboard.server.common.data.device.profile.ProtoTransportPayloadConfiguration; |
|||
import org.thingsboard.server.common.data.device.profile.TransportPayloadTypeConfiguration; |
|||
|
|||
import java.util.Arrays; |
|||
import java.util.List; |
|||
|
|||
import static org.junit.Assert.assertNotNull; |
|||
import static org.junit.Assert.assertTrue; |
|||
|
|||
@Slf4j |
|||
public abstract class AbstractCoapAttributesProtoIntegrationTest extends AbstractCoapAttributesIntegrationTest { |
|||
|
|||
@After |
|||
public void afterTest() throws Exception { |
|||
processAfterTest(); |
|||
} |
|||
|
|||
@Test |
|||
public void testPushAttributes() throws Exception { |
|||
super.processBeforeTest("Test Post Attributes device Proto", CoapDeviceType.DEFAULT, TransportPayloadType.PROTOBUF); |
|||
List<String> expectedKeys = Arrays.asList("key1", "key2", "key3", "key4", "key5"); |
|||
DeviceProfileTransportConfiguration transportConfiguration = deviceProfile.getProfileData().getTransportConfiguration(); |
|||
assertTrue(transportConfiguration instanceof CoapDeviceProfileTransportConfiguration); |
|||
CoapDeviceProfileTransportConfiguration coapTransportConfiguration = (CoapDeviceProfileTransportConfiguration) transportConfiguration; |
|||
CoapDeviceTypeConfiguration coapDeviceTypeConfiguration = coapTransportConfiguration.getCoapDeviceTypeConfiguration(); |
|||
assertTrue(coapDeviceTypeConfiguration instanceof DefaultCoapDeviceTypeConfiguration); |
|||
DefaultCoapDeviceTypeConfiguration defaultCoapDeviceTypeConfiguration = (DefaultCoapDeviceTypeConfiguration) coapDeviceTypeConfiguration; |
|||
TransportPayloadTypeConfiguration transportPayloadTypeConfiguration = defaultCoapDeviceTypeConfiguration.getTransportPayloadTypeConfiguration(); |
|||
assertTrue(transportPayloadTypeConfiguration instanceof ProtoTransportPayloadConfiguration); |
|||
ProtoTransportPayloadConfiguration protoTransportPayloadConfiguration = (ProtoTransportPayloadConfiguration) transportPayloadTypeConfiguration; |
|||
ProtoFileElement transportProtoSchemaFile = protoTransportPayloadConfiguration.getTransportProtoSchema(DEVICE_ATTRIBUTES_PROTO_SCHEMA); |
|||
DynamicSchema attributesSchema = protoTransportPayloadConfiguration.getDynamicSchema(transportProtoSchemaFile, ProtoTransportPayloadConfiguration.ATTRIBUTES_PROTO_SCHEMA); |
|||
|
|||
DynamicMessage.Builder nestedJsonObjectBuilder = attributesSchema.newMessageBuilder("PostAttributes.JsonObject.NestedJsonObject"); |
|||
Descriptors.Descriptor nestedJsonObjectBuilderDescriptor = nestedJsonObjectBuilder.getDescriptorForType(); |
|||
assertNotNull(nestedJsonObjectBuilderDescriptor); |
|||
DynamicMessage nestedJsonObject = nestedJsonObjectBuilder.setField(nestedJsonObjectBuilderDescriptor.findFieldByName("key"), "value").build(); |
|||
|
|||
DynamicMessage.Builder jsonObjectBuilder = attributesSchema.newMessageBuilder("PostAttributes.JsonObject"); |
|||
Descriptors.Descriptor jsonObjectBuilderDescriptor = jsonObjectBuilder.getDescriptorForType(); |
|||
assertNotNull(jsonObjectBuilderDescriptor); |
|||
DynamicMessage jsonObject = jsonObjectBuilder |
|||
.setField(jsonObjectBuilderDescriptor.findFieldByName("someNumber"), 42) |
|||
.addRepeatedField(jsonObjectBuilderDescriptor.findFieldByName("someArray"), 1) |
|||
.addRepeatedField(jsonObjectBuilderDescriptor.findFieldByName("someArray"), 2) |
|||
.addRepeatedField(jsonObjectBuilderDescriptor.findFieldByName("someArray"), 3) |
|||
.setField(jsonObjectBuilderDescriptor.findFieldByName("someNestedObject"), nestedJsonObject) |
|||
.build(); |
|||
|
|||
DynamicMessage.Builder postAttributesBuilder = attributesSchema.newMessageBuilder("PostAttributes"); |
|||
Descriptors.Descriptor postAttributesMsgDescriptor = postAttributesBuilder.getDescriptorForType(); |
|||
assertNotNull(postAttributesMsgDescriptor); |
|||
DynamicMessage postAttributesMsg = postAttributesBuilder |
|||
.setField(postAttributesMsgDescriptor.findFieldByName("key1"), "value1") |
|||
.setField(postAttributesMsgDescriptor.findFieldByName("key2"), true) |
|||
.setField(postAttributesMsgDescriptor.findFieldByName("key3"), 3.0) |
|||
.setField(postAttributesMsgDescriptor.findFieldByName("key4"), 4) |
|||
.setField(postAttributesMsgDescriptor.findFieldByName("key5"), jsonObject) |
|||
.build(); |
|||
processAttributesTest(expectedKeys, postAttributesMsg.toByteArray()); |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,26 @@ |
|||
/** |
|||
* 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.coap.telemetry.attributes.sql; |
|||
|
|||
import org.thingsboard.server.transport.coap.telemetry.attributes.AbstractCoapAttributesIntegrationTest; |
|||
import org.thingsboard.server.dao.service.DaoSqlTest; |
|||
|
|||
/** |
|||
* Created by Valerii Sosliuk on 8/22/2017. |
|||
*/ |
|||
@DaoSqlTest |
|||
public class CoapAttributesSqlIntegrationTest extends AbstractCoapAttributesIntegrationTest { |
|||
} |
|||
@ -0,0 +1,26 @@ |
|||
/** |
|||
* 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.coap.telemetry.attributes.sql; |
|||
|
|||
import org.thingsboard.server.transport.coap.telemetry.attributes.AbstractCoapAttributesJsonIntegrationTest; |
|||
import org.thingsboard.server.dao.service.DaoSqlTest; |
|||
|
|||
/** |
|||
* Created by Valerii Sosliuk on 8/22/2017. |
|||
*/ |
|||
@DaoSqlTest |
|||
public class CoapAttributesSqlJsonIntegrationTest extends AbstractCoapAttributesJsonIntegrationTest { |
|||
} |
|||
@ -0,0 +1,26 @@ |
|||
/** |
|||
* 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.coap.telemetry.attributes.sql; |
|||
|
|||
import org.thingsboard.server.transport.coap.telemetry.attributes.AbstractCoapAttributesProtoIntegrationTest; |
|||
import org.thingsboard.server.dao.service.DaoSqlTest; |
|||
|
|||
/** |
|||
* Created by Valerii Sosliuk on 8/22/2017. |
|||
*/ |
|||
@DaoSqlTest |
|||
public class CoapAttributesSqlProtoIntegrationTest extends AbstractCoapAttributesProtoIntegrationTest { |
|||
} |
|||
@ -0,0 +1,178 @@ |
|||
/** |
|||
* 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.coap.telemetry.timeseries; |
|||
|
|||
import com.fasterxml.jackson.core.type.TypeReference; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.eclipse.californium.core.CoapClient; |
|||
import org.eclipse.californium.core.CoapResponse; |
|||
import org.eclipse.californium.core.coap.CoAP; |
|||
import org.eclipse.californium.core.coap.MediaTypeRegistry; |
|||
import org.eclipse.californium.elements.exception.ConnectorException; |
|||
import org.junit.After; |
|||
import org.junit.Before; |
|||
import org.junit.Test; |
|||
import org.thingsboard.server.transport.coap.AbstractCoapIntegrationTest; |
|||
import org.thingsboard.server.common.msg.session.FeatureType; |
|||
|
|||
import java.io.IOException; |
|||
import java.util.Arrays; |
|||
import java.util.HashSet; |
|||
import java.util.List; |
|||
import java.util.Map; |
|||
import java.util.Set; |
|||
|
|||
import static org.junit.Assert.assertEquals; |
|||
import static org.junit.Assert.assertNotNull; |
|||
|
|||
@Slf4j |
|||
public abstract class AbstractCoapTimeseriesIntegrationTest extends AbstractCoapIntegrationTest { |
|||
|
|||
private static final String PAYLOAD_VALUES_STR = "{\"key1\":\"value1\", \"key2\":true, \"key3\": 3.0, \"key4\": 4," + |
|||
" \"key5\": {\"someNumber\": 42, \"someArray\": [1,2,3], \"someNestedObject\": {\"key\": \"value\"}}}"; |
|||
|
|||
@Before |
|||
public void beforeTest() throws Exception { |
|||
processBeforeTest("Test Post Telemetry device", null, null); |
|||
} |
|||
|
|||
@After |
|||
public void afterTest() throws Exception { |
|||
processAfterTest(); |
|||
} |
|||
|
|||
@Test |
|||
public void testPushTelemetry() throws Exception { |
|||
processTestPostTelemetry(null, false); |
|||
} |
|||
|
|||
@Test |
|||
public void testPushTelemetryWithTs() throws Exception { |
|||
String payloadStr = "{\"ts\": 10000, \"values\": " + PAYLOAD_VALUES_STR + "}"; |
|||
processTestPostTelemetry(payloadStr.getBytes(), true); |
|||
} |
|||
|
|||
protected void processTestPostTelemetry(byte[] payloadBytes, boolean withTs) throws Exception { |
|||
log.warn("[testPushTelemetry] Device: {}, Transport type: {}", savedDevice.getName(), savedDevice.getType()); |
|||
List<String> expectedKeys = Arrays.asList("key1", "key2", "key3", "key4", "key5"); |
|||
CoapClient coapClient = getCoapClient(FeatureType.TELEMETRY); |
|||
postTelemetry(coapClient, payloadBytes); |
|||
|
|||
String deviceId = savedDevice.getId().getId().toString(); |
|||
|
|||
long start = System.currentTimeMillis(); |
|||
long end = System.currentTimeMillis() + 5000; |
|||
|
|||
List<String> actualKeys = null; |
|||
while (start <= end) { |
|||
actualKeys = doGetAsyncTyped("/api/plugins/telemetry/DEVICE/" + deviceId + "/keys/timeseries", new TypeReference<>() {}); |
|||
if (actualKeys.size() == expectedKeys.size()) { |
|||
break; |
|||
} |
|||
Thread.sleep(100); |
|||
start += 100; |
|||
} |
|||
assertNotNull(actualKeys); |
|||
|
|||
Set<String> actualKeySet = new HashSet<>(actualKeys); |
|||
Set<String> expectedKeySet = new HashSet<>(expectedKeys); |
|||
|
|||
assertEquals(expectedKeySet, actualKeySet); |
|||
|
|||
String getTelemetryValuesUrl; |
|||
if (withTs) { |
|||
getTelemetryValuesUrl = "/api/plugins/telemetry/DEVICE/" + deviceId + "/values/timeseries?startTs=0&endTs=15000&keys=" + String.join(",", actualKeySet); |
|||
} else { |
|||
getTelemetryValuesUrl = "/api/plugins/telemetry/DEVICE/" + deviceId + "/values/timeseries?keys=" + String.join(",", actualKeySet); |
|||
} |
|||
start = System.currentTimeMillis(); |
|||
end = System.currentTimeMillis() + 5000; |
|||
Map<String, List<Map<String, Object>>> values = null; |
|||
while (start <= end) { |
|||
values = doGetAsyncTyped(getTelemetryValuesUrl, new TypeReference<>() {}); |
|||
boolean valid = values.size() == expectedKeys.size(); |
|||
if (valid) { |
|||
for (String key : expectedKeys) { |
|||
List<Map<String, Object>> tsValues = values.get(key); |
|||
if (tsValues != null && tsValues.size() > 0) { |
|||
Object ts = tsValues.get(0).get("ts"); |
|||
if (ts == null) { |
|||
valid = false; |
|||
break; |
|||
} |
|||
} else { |
|||
valid = false; |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
if (valid) { |
|||
break; |
|||
} |
|||
Thread.sleep(100); |
|||
start += 100; |
|||
} |
|||
assertNotNull(values); |
|||
|
|||
if (withTs) { |
|||
assertTs(values, expectedKeys, 10000, 0); |
|||
} |
|||
assertValues(values, 0); |
|||
} |
|||
|
|||
private void postTelemetry(CoapClient client, byte[] payload) throws IOException, ConnectorException { |
|||
if (payload == null) { |
|||
payload = PAYLOAD_VALUES_STR.getBytes(); |
|||
} |
|||
CoapResponse coapResponse = client.setTimeout((long) 60000).post(payload, MediaTypeRegistry.APPLICATION_JSON); |
|||
assertEquals(CoAP.ResponseCode.CREATED, coapResponse.getCode()); |
|||
} |
|||
|
|||
private void assertTs(Map<String, List<Map<String, Object>>> deviceValues, List<String> expectedKeys, int ts, int arrayIndex) { |
|||
assertEquals(ts, deviceValues.get(expectedKeys.get(0)).get(arrayIndex).get("ts")); |
|||
assertEquals(ts, deviceValues.get(expectedKeys.get(1)).get(arrayIndex).get("ts")); |
|||
assertEquals(ts, deviceValues.get(expectedKeys.get(2)).get(arrayIndex).get("ts")); |
|||
assertEquals(ts, deviceValues.get(expectedKeys.get(3)).get(arrayIndex).get("ts")); |
|||
assertEquals(ts, deviceValues.get(expectedKeys.get(4)).get(arrayIndex).get("ts")); |
|||
} |
|||
|
|||
private void assertValues(Map<String, List<Map<String, Object>>> deviceValues, int arrayIndex) { |
|||
for (Map.Entry<String, List<Map<String, Object>>> entry : deviceValues.entrySet()) { |
|||
String key = entry.getKey(); |
|||
List<Map<String, Object>> tsKv = entry.getValue(); |
|||
String value = (String) tsKv.get(arrayIndex).get("value"); |
|||
switch (key) { |
|||
case "key1": |
|||
assertEquals("value1", value); |
|||
break; |
|||
case "key2": |
|||
assertEquals("true", value); |
|||
break; |
|||
case "key3": |
|||
assertEquals("3.0", value); |
|||
break; |
|||
case "key4": |
|||
assertEquals("4", value); |
|||
break; |
|||
case "key5": |
|||
assertEquals("{\"someNumber\":42,\"someArray\":[1,2,3],\"someNestedObject\":{\"key\":\"value\"}}", value); |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
} |
|||
@ -0,0 +1,50 @@ |
|||
/** |
|||
* 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.coap.telemetry.timeseries; |
|||
|
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.junit.After; |
|||
import org.junit.Before; |
|||
import org.junit.Test; |
|||
import org.thingsboard.server.common.data.CoapDeviceType; |
|||
import org.thingsboard.server.common.data.TransportPayloadType; |
|||
|
|||
@Slf4j |
|||
public abstract class AbstractCoapTimeseriesJsonIntegrationTest extends AbstractCoapTimeseriesIntegrationTest { |
|||
|
|||
@Before |
|||
public void beforeTest() throws Exception { |
|||
processBeforeTest("Test Post Telemetry device json payload", CoapDeviceType.DEFAULT, TransportPayloadType.JSON); |
|||
} |
|||
|
|||
@After |
|||
public void afterTest() throws Exception { |
|||
processAfterTest(); |
|||
} |
|||
|
|||
|
|||
@Test |
|||
public void testPushTelemetry() throws Exception { |
|||
super.testPushTelemetry(); |
|||
} |
|||
|
|||
@Test |
|||
public void testPushTelemetryWithTs() throws Exception { |
|||
super.testPushTelemetryWithTs(); |
|||
} |
|||
|
|||
|
|||
} |
|||
@ -0,0 +1,170 @@ |
|||
/** |
|||
* 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.coap.telemetry.timeseries; |
|||
|
|||
import com.github.os72.protobuf.dynamic.DynamicSchema; |
|||
import com.google.protobuf.Descriptors; |
|||
import com.google.protobuf.DynamicMessage; |
|||
import com.squareup.wire.schema.internal.parser.ProtoFileElement; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.junit.After; |
|||
import org.junit.Test; |
|||
import org.thingsboard.server.common.data.CoapDeviceType; |
|||
import org.thingsboard.server.common.data.DeviceProfileProvisionType; |
|||
import org.thingsboard.server.common.data.TransportPayloadType; |
|||
import org.thingsboard.server.common.data.device.profile.CoapDeviceProfileTransportConfiguration; |
|||
import org.thingsboard.server.common.data.device.profile.CoapDeviceTypeConfiguration; |
|||
import org.thingsboard.server.common.data.device.profile.DefaultCoapDeviceTypeConfiguration; |
|||
import org.thingsboard.server.common.data.device.profile.DeviceProfileTransportConfiguration; |
|||
import org.thingsboard.server.common.data.device.profile.ProtoTransportPayloadConfiguration; |
|||
import org.thingsboard.server.common.data.device.profile.TransportPayloadTypeConfiguration; |
|||
|
|||
import static org.junit.Assert.assertNotNull; |
|||
import static org.junit.Assert.assertTrue; |
|||
|
|||
@Slf4j |
|||
public abstract class AbstractCoapTimeseriesProtoIntegrationTest extends AbstractCoapTimeseriesIntegrationTest { |
|||
|
|||
@After |
|||
public void afterTest() throws Exception { |
|||
processAfterTest(); |
|||
} |
|||
|
|||
@Test |
|||
public void testPushTelemetry() throws Exception { |
|||
super.processBeforeTest("Test Post Telemetry device proto payload", CoapDeviceType.DEFAULT, TransportPayloadType.PROTOBUF); |
|||
DeviceProfileTransportConfiguration transportConfiguration = deviceProfile.getProfileData().getTransportConfiguration(); |
|||
assertTrue(transportConfiguration instanceof CoapDeviceProfileTransportConfiguration); |
|||
CoapDeviceProfileTransportConfiguration coapDeviceProfileTransportConfiguration = (CoapDeviceProfileTransportConfiguration) transportConfiguration; |
|||
CoapDeviceTypeConfiguration coapDeviceTypeConfiguration = coapDeviceProfileTransportConfiguration.getCoapDeviceTypeConfiguration(); |
|||
assertTrue(coapDeviceTypeConfiguration instanceof DefaultCoapDeviceTypeConfiguration); |
|||
DefaultCoapDeviceTypeConfiguration defaultCoapDeviceTypeConfiguration = (DefaultCoapDeviceTypeConfiguration) coapDeviceTypeConfiguration; |
|||
TransportPayloadTypeConfiguration transportPayloadTypeConfiguration = defaultCoapDeviceTypeConfiguration.getTransportPayloadTypeConfiguration(); |
|||
assertTrue(transportPayloadTypeConfiguration instanceof ProtoTransportPayloadConfiguration); |
|||
ProtoTransportPayloadConfiguration protoTransportPayloadConfiguration = (ProtoTransportPayloadConfiguration) transportPayloadTypeConfiguration; |
|||
ProtoFileElement transportProtoSchema = protoTransportPayloadConfiguration.getTransportProtoSchema(DEVICE_TELEMETRY_PROTO_SCHEMA); |
|||
DynamicSchema telemetrySchema = protoTransportPayloadConfiguration.getDynamicSchema(transportProtoSchema, "telemetrySchema"); |
|||
|
|||
DynamicMessage.Builder nestedJsonObjectBuilder = telemetrySchema.newMessageBuilder("PostTelemetry.JsonObject.NestedJsonObject"); |
|||
Descriptors.Descriptor nestedJsonObjectBuilderDescriptor = nestedJsonObjectBuilder.getDescriptorForType(); |
|||
assertNotNull(nestedJsonObjectBuilderDescriptor); |
|||
DynamicMessage nestedJsonObject = nestedJsonObjectBuilder.setField(nestedJsonObjectBuilderDescriptor.findFieldByName("key"), "value").build(); |
|||
|
|||
DynamicMessage.Builder jsonObjectBuilder = telemetrySchema.newMessageBuilder("PostTelemetry.JsonObject"); |
|||
Descriptors.Descriptor jsonObjectBuilderDescriptor = jsonObjectBuilder.getDescriptorForType(); |
|||
assertNotNull(jsonObjectBuilderDescriptor); |
|||
DynamicMessage jsonObject = jsonObjectBuilder |
|||
.setField(jsonObjectBuilderDescriptor.findFieldByName("someNumber"), 42) |
|||
.addRepeatedField(jsonObjectBuilderDescriptor.findFieldByName("someArray"), 1) |
|||
.addRepeatedField(jsonObjectBuilderDescriptor.findFieldByName("someArray"), 2) |
|||
.addRepeatedField(jsonObjectBuilderDescriptor.findFieldByName("someArray"), 3) |
|||
.setField(jsonObjectBuilderDescriptor.findFieldByName("someNestedObject"), nestedJsonObject) |
|||
.build(); |
|||
|
|||
DynamicMessage.Builder postTelemetryBuilder = telemetrySchema.newMessageBuilder("PostTelemetry"); |
|||
Descriptors.Descriptor postTelemetryMsgDescriptor = postTelemetryBuilder.getDescriptorForType(); |
|||
assertNotNull(postTelemetryMsgDescriptor); |
|||
DynamicMessage postTelemetryMsg = postTelemetryBuilder |
|||
.setField(postTelemetryMsgDescriptor.findFieldByName("key1"), "value1") |
|||
.setField(postTelemetryMsgDescriptor.findFieldByName("key2"), true) |
|||
.setField(postTelemetryMsgDescriptor.findFieldByName("key3"), 3.0) |
|||
.setField(postTelemetryMsgDescriptor.findFieldByName("key4"), 4) |
|||
.setField(postTelemetryMsgDescriptor.findFieldByName("key5"), jsonObject) |
|||
.build(); |
|||
processTestPostTelemetry(postTelemetryMsg.toByteArray(), false); |
|||
} |
|||
|
|||
@Test |
|||
public void testPushTelemetryWithTs() throws Exception { |
|||
String schemaStr = "syntax =\"proto3\";\n" + |
|||
"\n" + |
|||
"package test;\n" + |
|||
"\n" + |
|||
"message PostTelemetry {\n" + |
|||
" int64 ts = 1;\n" + |
|||
" Values values = 2;\n" + |
|||
" \n" + |
|||
" message Values {\n" + |
|||
" string key1 = 3;\n" + |
|||
" bool key2 = 4;\n" + |
|||
" double key3 = 5;\n" + |
|||
" int32 key4 = 6;\n" + |
|||
" JsonObject key5 = 7;\n" + |
|||
" }\n" + |
|||
" \n" + |
|||
" message JsonObject {\n" + |
|||
" int32 someNumber = 8;\n" + |
|||
" repeated int32 someArray = 9;\n" + |
|||
" NestedJsonObject someNestedObject = 10;\n" + |
|||
" message NestedJsonObject {\n" + |
|||
" string key = 11;\n" + |
|||
" }\n" + |
|||
" }\n" + |
|||
"}"; |
|||
super.processBeforeTest("Test Post Telemetry device proto payload", CoapDeviceType.DEFAULT, TransportPayloadType.PROTOBUF, schemaStr, null, DeviceProfileProvisionType.DISABLED, null, null); |
|||
DeviceProfileTransportConfiguration transportConfiguration = deviceProfile.getProfileData().getTransportConfiguration(); |
|||
assertTrue(transportConfiguration instanceof CoapDeviceProfileTransportConfiguration); |
|||
CoapDeviceProfileTransportConfiguration coapDeviceProfileTransportConfiguration = (CoapDeviceProfileTransportConfiguration) transportConfiguration; |
|||
CoapDeviceTypeConfiguration coapDeviceTypeConfiguration = coapDeviceProfileTransportConfiguration.getCoapDeviceTypeConfiguration(); |
|||
assertTrue(coapDeviceTypeConfiguration instanceof DefaultCoapDeviceTypeConfiguration); |
|||
DefaultCoapDeviceTypeConfiguration defaultCoapDeviceTypeConfiguration = (DefaultCoapDeviceTypeConfiguration) coapDeviceTypeConfiguration; |
|||
TransportPayloadTypeConfiguration transportPayloadTypeConfiguration = defaultCoapDeviceTypeConfiguration.getTransportPayloadTypeConfiguration(); |
|||
assertTrue(transportPayloadTypeConfiguration instanceof ProtoTransportPayloadConfiguration); |
|||
ProtoTransportPayloadConfiguration protoTransportPayloadConfiguration = (ProtoTransportPayloadConfiguration) transportPayloadTypeConfiguration; |
|||
ProtoFileElement transportProtoSchema = protoTransportPayloadConfiguration.getTransportProtoSchema(schemaStr); |
|||
DynamicSchema telemetrySchema = protoTransportPayloadConfiguration.getDynamicSchema(transportProtoSchema, "telemetrySchema"); |
|||
|
|||
DynamicMessage.Builder nestedJsonObjectBuilder = telemetrySchema.newMessageBuilder("PostTelemetry.JsonObject.NestedJsonObject"); |
|||
Descriptors.Descriptor nestedJsonObjectBuilderDescriptor = nestedJsonObjectBuilder.getDescriptorForType(); |
|||
assertNotNull(nestedJsonObjectBuilderDescriptor); |
|||
DynamicMessage nestedJsonObject = nestedJsonObjectBuilder.setField(nestedJsonObjectBuilderDescriptor.findFieldByName("key"), "value").build(); |
|||
|
|||
DynamicMessage.Builder jsonObjectBuilder = telemetrySchema.newMessageBuilder("PostTelemetry.JsonObject"); |
|||
Descriptors.Descriptor jsonObjectBuilderDescriptor = jsonObjectBuilder.getDescriptorForType(); |
|||
assertNotNull(jsonObjectBuilderDescriptor); |
|||
DynamicMessage jsonObject = jsonObjectBuilder |
|||
.setField(jsonObjectBuilderDescriptor.findFieldByName("someNumber"), 42) |
|||
.addRepeatedField(jsonObjectBuilderDescriptor.findFieldByName("someArray"), 1) |
|||
.addRepeatedField(jsonObjectBuilderDescriptor.findFieldByName("someArray"), 2) |
|||
.addRepeatedField(jsonObjectBuilderDescriptor.findFieldByName("someArray"), 3) |
|||
.setField(jsonObjectBuilderDescriptor.findFieldByName("someNestedObject"), nestedJsonObject) |
|||
.build(); |
|||
|
|||
|
|||
DynamicMessage.Builder valuesBuilder = telemetrySchema.newMessageBuilder("PostTelemetry.Values"); |
|||
Descriptors.Descriptor valuesDescriptor = valuesBuilder.getDescriptorForType(); |
|||
assertNotNull(valuesDescriptor); |
|||
|
|||
DynamicMessage valuesMsg = valuesBuilder |
|||
.setField(valuesDescriptor.findFieldByName("key1"), "value1") |
|||
.setField(valuesDescriptor.findFieldByName("key2"), true) |
|||
.setField(valuesDescriptor.findFieldByName("key3"), 3.0) |
|||
.setField(valuesDescriptor.findFieldByName("key4"), 4) |
|||
.setField(valuesDescriptor.findFieldByName("key5"), jsonObject) |
|||
.build(); |
|||
|
|||
DynamicMessage.Builder postTelemetryBuilder = telemetrySchema.newMessageBuilder("PostTelemetry"); |
|||
Descriptors.Descriptor postTelemetryMsgDescriptor = postTelemetryBuilder.getDescriptorForType(); |
|||
assertNotNull(postTelemetryMsgDescriptor); |
|||
DynamicMessage postTelemetryMsg = postTelemetryBuilder |
|||
.setField(postTelemetryMsgDescriptor.findFieldByName("ts"), 10000L) |
|||
.setField(postTelemetryMsgDescriptor.findFieldByName("values"), valuesMsg) |
|||
.build(); |
|||
|
|||
processTestPostTelemetry(postTelemetryMsg.toByteArray(), true); |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,26 @@ |
|||
/** |
|||
* 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.coap.telemetry.timeseries.sql; |
|||
|
|||
import org.thingsboard.server.transport.coap.telemetry.timeseries.AbstractCoapTimeseriesIntegrationTest; |
|||
import org.thingsboard.server.dao.service.DaoSqlTest; |
|||
|
|||
/** |
|||
* Created by Valerii Sosliuk on 8/22/2017. |
|||
*/ |
|||
@DaoSqlTest |
|||
public class CoapTimeseriesSqlIntegrationTest extends AbstractCoapTimeseriesIntegrationTest { |
|||
} |
|||
@ -0,0 +1,26 @@ |
|||
/** |
|||
* 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.coap.telemetry.timeseries.sql; |
|||
|
|||
import org.thingsboard.server.transport.coap.telemetry.timeseries.AbstractCoapTimeseriesJsonIntegrationTest; |
|||
import org.thingsboard.server.dao.service.DaoSqlTest; |
|||
|
|||
/** |
|||
* Created by Valerii Sosliuk on 8/22/2017. |
|||
*/ |
|||
@DaoSqlTest |
|||
public class CoapTimeseriesSqlJsonIntegrationTest extends AbstractCoapTimeseriesJsonIntegrationTest { |
|||
} |
|||
@ -0,0 +1,26 @@ |
|||
/** |
|||
* 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.coap.telemetry.timeseries.sql; |
|||
|
|||
import org.thingsboard.server.transport.coap.telemetry.timeseries.AbstractCoapTimeseriesProtoIntegrationTest; |
|||
import org.thingsboard.server.dao.service.DaoSqlTest; |
|||
|
|||
/** |
|||
* Created by Valerii Sosliuk on 8/22/2017. |
|||
*/ |
|||
@DaoSqlTest |
|||
public class CoapTimeseriesSqlProtoIntegrationTest extends AbstractCoapTimeseriesProtoIntegrationTest { |
|||
} |
|||
@ -0,0 +1,21 @@ |
|||
/** |
|||
* 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.common.data; |
|||
|
|||
public enum CoapDeviceType { |
|||
DEFAULT, |
|||
EFENTO |
|||
} |
|||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue