Browse Source

Device Profile Proto Improvement

pull/3740/head
Andrii Shvaika 6 years ago
parent
commit
706fd01d76
  1. 12
      application/src/test/java/org/thingsboard/server/mqtt/MqttSqlTestSuite.java
  2. 1
      application/src/test/java/org/thingsboard/server/mqtt/attributes/AbstractMqttAttributesIntegrationTest.java
  3. 2
      application/src/test/java/org/thingsboard/server/mqtt/attributes/request/AbstractMqttAttributesRequestIntegrationTest.java
  4. 4
      application/src/test/java/org/thingsboard/server/mqtt/attributes/request/AbstractMqttAttributesRequestProtoIntegrationTest.java
  5. 9
      common/data/src/main/java/org/thingsboard/server/common/data/device/profile/MqttDeviceProfileTransportConfiguration.java
  6. 3
      common/data/src/main/java/org/thingsboard/server/common/data/device/profile/ProtoTransportPayloadConfiguration.java
  7. 2
      common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/DeviceSessionCtx.java
  8. 51
      common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/adaptor/JsonConverter.java
  9. 25
      dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileServiceImpl.java
  10. 2
      ui-ngx/src/app/modules/home/components/profile/device/mqtt-device-profile-transport-configuration.component.ts

12
application/src/test/java/org/thingsboard/server/mqtt/MqttSqlTestSuite.java

@ -26,13 +26,13 @@ import java.util.Arrays;
@RunWith(ClasspathSuite.class) @RunWith(ClasspathSuite.class)
@ClasspathSuite.ClassnameFilters({ @ClasspathSuite.ClassnameFilters({
"org.thingsboard.server.mqtt.rpc.sql.*Test", // "org.thingsboard.server.mqtt.rpc.sql.*Test",
"org.thingsboard.server.mqtt.telemetry.timeseries.sql.*Test", // "org.thingsboard.server.mqtt.telemetry.timeseries.sql.*Test",
"org.thingsboard.server.mqtt.telemetry.attributes.sql.*Test", // "org.thingsboard.server.mqtt.telemetry.attributes.sql.*Test",
"org.thingsboard.server.mqtt.attributes.updates.sql.*Test", // "org.thingsboard.server.mqtt.attributes.updates.sql.*Test",
"org.thingsboard.server.mqtt.attributes.request.sql.*Test", "org.thingsboard.server.mqtt.attributes.request.sql.*Test",
"org.thingsboard.server.mqtt.claim.sql.*Test", // "org.thingsboard.server.mqtt.claim.sql.*Test",
"org.thingsboard.server.mqtt.provision.sql.*Test" // "org.thingsboard.server.mqtt.provision.sql.*Test"
}) })
public class MqttSqlTestSuite { public class MqttSqlTestSuite {

1
application/src/test/java/org/thingsboard/server/mqtt/attributes/AbstractMqttAttributesIntegrationTest.java

@ -56,7 +56,6 @@ public abstract class AbstractMqttAttributesIntegrationTest extends AbstractMqtt
return tsKvProtoList; return tsKvProtoList;
} }
protected TransportProtos.TsKvProto getTsKvProto(String key, String value, TransportProtos.KeyValueType keyValueType) { protected TransportProtos.TsKvProto getTsKvProto(String key, String value, TransportProtos.KeyValueType keyValueType) {
TransportProtos.TsKvProto.Builder tsKvProtoBuilder = TransportProtos.TsKvProto.newBuilder(); TransportProtos.TsKvProto.Builder tsKvProtoBuilder = TransportProtos.TsKvProto.newBuilder();
TransportProtos.KeyValueProto keyValueProto = getKeyValueProto(key, value, keyValueType); TransportProtos.KeyValueProto keyValueProto = getKeyValueProto(key, value, keyValueType);

2
application/src/test/java/org/thingsboard/server/mqtt/attributes/request/AbstractMqttAttributesRequestIntegrationTest.java

@ -122,7 +122,7 @@ public abstract class AbstractMqttAttributesRequestIntegrationTest extends Abstr
client.publish(MqttTopics.DEVICE_ATTRIBUTES_REQUEST_TOPIC_PREFIX + "1", mqttMessage); client.publish(MqttTopics.DEVICE_ATTRIBUTES_REQUEST_TOPIC_PREFIX + "1", mqttMessage);
latch.await(3, TimeUnit.SECONDS); latch.await(3, TimeUnit.SECONDS);
assertEquals(MqttQoS.AT_MOST_ONCE.value(), callback.getQoS()); assertEquals(MqttQoS.AT_MOST_ONCE.value(), callback.getQoS());
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\"}}}}"; String expectedRequestPayload = "{\"client\":{\"attribute5\":{\"someNumber\":42,\"someArray\":[1,2,3],\"someNestedObject\":{\"key\":\"value\"}},\"attribute4\":73,\"attribute1\":\"value1\",\"attribute3\":42.0,\"attribute2\":true},\"shared\":{\"attribute5\":{\"someNumber\":42,\"someArray\":[1,2,3],\"someNestedObject\":{\"key\":\"value\"}},\"attribute4\":73,\"attribute1\":\"value1\",\"attribute3\":42.0,\"attribute2\":true}}";
assertEquals(JacksonUtil.toJsonNode(expectedRequestPayload), JacksonUtil.toJsonNode(new String(callback.getPayloadBytes(), StandardCharsets.UTF_8))); assertEquals(JacksonUtil.toJsonNode(expectedRequestPayload), JacksonUtil.toJsonNode(new String(callback.getPayloadBytes(), StandardCharsets.UTF_8)));
} }

4
application/src/test/java/org/thingsboard/server/mqtt/attributes/request/AbstractMqttAttributesRequestProtoIntegrationTest.java

@ -72,11 +72,11 @@ public abstract class AbstractMqttAttributesRequestProtoIntegrationTest extends
@Test @Test
public void testRequestAttributesValuesFromTheServer() throws Exception { public void testRequestAttributesValuesFromTheServer() throws Exception {
super.processBeforeTest("Test Request attribute values from the server proto", "Gateway Test Request attribute values from the server proto", TransportPayloadType.PROTOBUF, null, null, null, ATTRIBUTES_SCHEMA_STR, DeviceProfileProvisionType.DISABLED, null, null); super.processBeforeTest("Test Request attribute values from the server proto", "Gateway Test Request attribute values from the server proto",
TransportPayloadType.PROTOBUF, null, null, null, ATTRIBUTES_SCHEMA_STR, DeviceProfileProvisionType.DISABLED, null, null);
processTestRequestAttributesValuesFromTheServer(); processTestRequestAttributesValuesFromTheServer();
} }
@Test @Test
public void testRequestAttributesValuesFromTheServerGateway() throws Exception { public void testRequestAttributesValuesFromTheServerGateway() throws Exception {
super.processBeforeTest("Test Request attribute values from the server proto", "Gateway Test Request attribute values from the server proto", TransportPayloadType.PROTOBUF, null, null); super.processBeforeTest("Test Request attribute values from the server proto", "Gateway Test Request attribute values from the server proto", TransportPayloadType.PROTOBUF, null, null);

9
common/data/src/main/java/org/thingsboard/server/common/data/device/profile/MqttDeviceProfileTransportConfiguration.java

@ -30,4 +30,13 @@ public class MqttDeviceProfileTransportConfiguration implements DeviceProfileTra
return DeviceTransportType.MQTT; return DeviceTransportType.MQTT;
} }
public TransportPayloadTypeConfiguration getTransportPayloadTypeConfiguration() {
if (transportPayloadTypeConfiguration != null) {
return transportPayloadTypeConfiguration;
} else {
return new JsonTransportPayloadConfiguration();
}
}
} }

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

@ -15,6 +15,7 @@
*/ */
package org.thingsboard.server.common.data.device.profile; package org.thingsboard.server.common.data.device.profile;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.github.os72.protobuf.dynamic.DynamicSchema; import com.github.os72.protobuf.dynamic.DynamicSchema;
import com.github.os72.protobuf.dynamic.EnumDefinition; import com.github.os72.protobuf.dynamic.EnumDefinition;
import com.github.os72.protobuf.dynamic.MessageDefinition; import com.github.os72.protobuf.dynamic.MessageDefinition;
@ -135,7 +136,7 @@ public class ProtoTransportPayloadConfiguration implements TransportPayloadTypeC
addMessageFieldsToTheMessageDefinition(messageElementFields, messageDefinitionBuilder); addMessageFieldsToTheMessageDefinition(messageElementFields, messageDefinitionBuilder);
} }
if (!oneOfs.isEmpty()) { if (!oneOfs.isEmpty()) {
for (OneOfElement oneOfelement: oneOfs) { for (OneOfElement oneOfelement : oneOfs) {
MessageDefinition.OneofBuilder oneofBuilder = messageDefinitionBuilder.addOneof(oneOfelement.getName()); MessageDefinition.OneofBuilder oneofBuilder = messageDefinitionBuilder.addOneof(oneOfelement.getName());
addMessageFieldsToTheOneOfDefinition(oneOfelement.getFields(), oneofBuilder); addMessageFieldsToTheOneOfDefinition(oneOfelement.getFields(), oneofBuilder);
} }

2
common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/DeviceSessionCtx.java

@ -123,7 +123,7 @@ public class DeviceSessionCtx extends MqttDeviceAwareSessionContext {
payloadType = transportPayloadTypeConfiguration.getTransportPayloadType(); payloadType = transportPayloadTypeConfiguration.getTransportPayloadType();
telemetryTopicFilter = MqttTopicFilterFactory.toFilter(mqttConfig.getDeviceTelemetryTopic()); telemetryTopicFilter = MqttTopicFilterFactory.toFilter(mqttConfig.getDeviceTelemetryTopic());
attributesTopicFilter = MqttTopicFilterFactory.toFilter(mqttConfig.getDeviceAttributesTopic()); attributesTopicFilter = MqttTopicFilterFactory.toFilter(mqttConfig.getDeviceAttributesTopic());
if (transportPayloadTypeConfiguration instanceof ProtoTransportPayloadConfiguration) { if (TransportPayloadType.PROTOBUF.equals(payloadType)) {
updateDynamicMessageDescriptors(transportPayloadTypeConfiguration); updateDynamicMessageDescriptors(transportPayloadTypeConfiguration);
} }
} else { } else {

51
common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/adaptor/JsonConverter.java

@ -19,7 +19,6 @@ import com.google.gson.Gson;
import com.google.gson.JsonArray; import com.google.gson.JsonArray;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonParser; import com.google.gson.JsonParser;
import com.google.gson.JsonPrimitive; import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSyntaxException; import com.google.gson.JsonSyntaxException;
@ -194,62 +193,34 @@ public class JsonConverter {
String message = String.format("String value length [%d] for key [%s] is greater than maximum allowed [%d]", value.getAsString().length(), valueEntry.getKey(), maxStringValueLength); String message = String.format("String value length [%d] for key [%s] is greater than maximum allowed [%d]", value.getAsString().length(), valueEntry.getKey(), maxStringValueLength);
throw new JsonSyntaxException(message); throw new JsonSyntaxException(message);
} }
if (isTypeCastEnabled) { if (isTypeCastEnabled && NumberUtils.isParsable(value.getAsString())) {
if (NumberUtils.isParsable(value.getAsString())) { try {
try { result.add(buildNumericKeyValueProto(value, valueEntry.getKey()));
result.add(buildNumericKeyValueProto(value, valueEntry.getKey())); } catch (RuntimeException th) {
} catch (RuntimeException th) { result.add(KeyValueProto.newBuilder().setKey(valueEntry.getKey()).setType(KeyValueType.STRING_V)
result.add(buildStringKVProto(valueEntry, value)); .setStringV(value.getAsString()).build());
}
} else {
try {
JsonElement jsonElement = JSON_PARSER.parse(value.getAsString());
if (jsonElement.isJsonObject() || jsonElement.isJsonArray()) {
result.add(buildJsonKVProto(valueEntry, jsonElement));
} else {
result.add(buildStringKVProto(valueEntry, value));
}
} catch (JsonParseException e) {
result.add(buildStringKVProto(valueEntry, value));
}
} }
} else { } else {
result.add(buildStringKVProto(valueEntry, value)); result.add(KeyValueProto.newBuilder().setKey(valueEntry.getKey()).setType(KeyValueType.STRING_V)
.setStringV(value.getAsString()).build());
} }
} else if (value.isBoolean()) { } else if (value.isBoolean()) {
result.add(KeyValueProto.newBuilder().setKey(valueEntry.getKey()).setType(KeyValueType.BOOLEAN_V) result.add(KeyValueProto.newBuilder().setKey(valueEntry.getKey()).setType(KeyValueType.BOOLEAN_V)
.setBoolV(value.getAsBoolean()).build()); .setBoolV(value.getAsBoolean()).build());
} else if (value.isNumber()) { } else if (value.isNumber()) {
result.add(buildNumericKeyValueProto(value, valueEntry.getKey())); result.add(buildNumericKeyValueProto(value, valueEntry.getKey()));
} else { } else if (!value.isJsonNull()) {
throw new JsonSyntaxException(CAN_T_PARSE_VALUE + value); throw new JsonSyntaxException(CAN_T_PARSE_VALUE + value);
} }
} else if (element.isJsonObject() || element.isJsonArray()) { } else if (element.isJsonObject() || element.isJsonArray()) {
result.add(buildJsonKVProto(valueEntry, element)); result.add(KeyValueProto.newBuilder().setKey(valueEntry.getKey()).setType(KeyValueType.JSON_V).setJsonV(element.toString()).build());
} else { } else if (!element.isJsonNull()) {
throw new JsonSyntaxException(CAN_T_PARSE_VALUE + element); throw new JsonSyntaxException(CAN_T_PARSE_VALUE + element);
} }
} }
return result; return result;
} }
private static KeyValueProto buildStringKVProto(Entry<String, JsonElement> valueEntry, JsonPrimitive value) {
return KeyValueProto.newBuilder()
.setKey(valueEntry.getKey())
.setType(KeyValueType.STRING_V)
.setStringV(value.getAsString())
.build();
}
private static KeyValueProto buildJsonKVProto(Entry<String, JsonElement> valueEntry, JsonElement jsonElement) {
return KeyValueProto
.newBuilder()
.setKey(valueEntry.getKey())
.setType(KeyValueType.JSON_V)
.setJsonV(jsonElement.toString())
.build();
}
private static KeyValueProto buildNumericKeyValueProto(JsonPrimitive value, String key) { private static KeyValueProto buildNumericKeyValueProto(JsonPrimitive value, String key) {
if (value.getAsString().contains(".")) { if (value.getAsString().contains(".")) {
return KeyValueProto.newBuilder() return KeyValueProto.newBuilder()

25
dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileServiceImpl.java

@ -331,18 +331,19 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D
if (defaultDeviceProfile != null && !defaultDeviceProfile.getId().equals(deviceProfile.getId())) { if (defaultDeviceProfile != null && !defaultDeviceProfile.getId().equals(deviceProfile.getId())) {
throw new DataValidationException("Another default device profile is present in scope of current tenant!"); throw new DataValidationException("Another default device profile is present in scope of current tenant!");
} }
} else { }
DeviceProfileTransportConfiguration transportConfiguration = deviceProfile.getProfileData().getTransportConfiguration();
if (transportConfiguration instanceof MqttDeviceProfileTransportConfiguration) { DeviceProfileTransportConfiguration transportConfiguration = deviceProfile.getProfileData().getTransportConfiguration();
MqttDeviceProfileTransportConfiguration mqttDeviceProfileTransportConfiguration = (MqttDeviceProfileTransportConfiguration) transportConfiguration; if (transportConfiguration instanceof MqttDeviceProfileTransportConfiguration) {
if (mqttDeviceProfileTransportConfiguration.getTransportPayloadTypeConfiguration() instanceof ProtoTransportPayloadConfiguration) { MqttDeviceProfileTransportConfiguration mqttTransportConfiguration = (MqttDeviceProfileTransportConfiguration) transportConfiguration;
ProtoTransportPayloadConfiguration protoTransportPayloadTypeConfiguration = (ProtoTransportPayloadConfiguration) mqttDeviceProfileTransportConfiguration.getTransportPayloadTypeConfiguration(); if (mqttTransportConfiguration.getTransportPayloadTypeConfiguration() instanceof ProtoTransportPayloadConfiguration) {
try { ProtoTransportPayloadConfiguration protoTransportPayloadTypeConfiguration =
validateTransportProtoSchema(protoTransportPayloadTypeConfiguration.getDeviceAttributesProtoSchema(), ATTRIBUTES_PROTO_SCHEMA); (ProtoTransportPayloadConfiguration) mqttTransportConfiguration.getTransportPayloadTypeConfiguration();
validateTransportProtoSchema(protoTransportPayloadTypeConfiguration.getDeviceTelemetryProtoSchema(), TELEMETRY_PROTO_SCHEMA); try {
} catch (Exception exception) { validateTransportProtoSchema(protoTransportPayloadTypeConfiguration.getDeviceAttributesProtoSchema(), ATTRIBUTES_PROTO_SCHEMA);
throw new DataValidationException(exception.getMessage()); validateTransportProtoSchema(protoTransportPayloadTypeConfiguration.getDeviceTelemetryProtoSchema(), TELEMETRY_PROTO_SCHEMA);
} } catch (Exception exception) {
throw new DataValidationException(exception.getMessage());
} }
} }
} }

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

@ -153,7 +153,7 @@ export class MqttDeviceProfileTransportConfigurationComponent implements Control
const defaultAttributesSchema = "syntax =\"proto3\";\n" + const defaultAttributesSchema = "syntax =\"proto3\";\n" +
"package attributes;\n" + "package attributes;\n" +
"\n" + "\n" +
"message SensorDataReading {\n" + "message SensorConfiguration {\n" +
" string firmwareVersion = 1;\n" + " string firmwareVersion = 1;\n" +
" string serialNumber = 2;\n" + " string serialNumber = 2;\n" +
"}"; "}";

Loading…
Cancel
Save