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