init commit
This commit is contained in:
parent
fd602dec7f
commit
8d4718320b
@ -29,7 +29,12 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
import org.thingsboard.server.common.data.DeviceProfile;
|
||||
import org.thingsboard.server.common.data.DeviceProfileInfo;
|
||||
import org.thingsboard.server.common.data.EntityType;
|
||||
import org.thingsboard.server.common.data.TransportPayloadType;
|
||||
import org.thingsboard.server.common.data.audit.ActionType;
|
||||
import org.thingsboard.server.common.data.device.profile.DeviceProfileTransportConfiguration;
|
||||
import org.thingsboard.server.common.data.device.profile.MqttDeviceProfileTransportConfiguration;
|
||||
import org.thingsboard.server.common.data.device.profile.MqttProtoDeviceProfileTransportConfiguration;
|
||||
import org.thingsboard.server.common.data.exception.ThingsboardErrorCode;
|
||||
import org.thingsboard.server.common.data.exception.ThingsboardException;
|
||||
import org.thingsboard.server.common.data.id.DeviceProfileId;
|
||||
import org.thingsboard.server.common.data.page.PageData;
|
||||
@ -92,6 +97,16 @@ public class DeviceProfileController extends BaseController {
|
||||
|
||||
checkEntity(deviceProfile.getId(), deviceProfile, Resource.DEVICE_PROFILE);
|
||||
|
||||
DeviceProfileTransportConfiguration transportConfiguration = deviceProfile.getProfileData().getTransportConfiguration();
|
||||
|
||||
if (transportConfiguration instanceof MqttDeviceProfileTransportConfiguration) {
|
||||
if (transportConfiguration instanceof MqttProtoDeviceProfileTransportConfiguration) {
|
||||
MqttProtoDeviceProfileTransportConfiguration protoTransportConfiguration = (MqttProtoDeviceProfileTransportConfiguration) transportConfiguration;
|
||||
if (protoTransportConfiguration.getTransportPayloadType().equals(TransportPayloadType.PROTOBUF))
|
||||
checkProtoSchemas(protoTransportConfiguration);
|
||||
}
|
||||
}
|
||||
|
||||
DeviceProfile savedDeviceProfile = checkNotNull(deviceProfileService.saveDeviceProfile(deviceProfile));
|
||||
|
||||
deviceProfileCache.put(savedDeviceProfile);
|
||||
@ -200,4 +215,14 @@ public class DeviceProfileController extends BaseController {
|
||||
throw handleException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkProtoSchemas(MqttProtoDeviceProfileTransportConfiguration mqttTransportConfiguration) throws ThingsboardException {
|
||||
try {
|
||||
mqttTransportConfiguration.validateTransportProtoSchema(mqttTransportConfiguration.getDeviceAttributesProtoSchema(), "attributes proto schema");
|
||||
mqttTransportConfiguration.validateTransportProtoSchema(mqttTransportConfiguration.getDeviceTelemetryProtoSchema(), "telemetry proto schema");
|
||||
} catch (Exception exception) {
|
||||
throw new ThingsboardException(exception.getMessage(), ThingsboardErrorCode.GENERAL);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -34,6 +34,8 @@ import org.thingsboard.server.common.data.User;
|
||||
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.MqttDeviceProfileTransportConfiguration;
|
||||
import org.thingsboard.server.common.data.device.profile.MqttJsonDeviceProfileTransportConfiguration;
|
||||
import org.thingsboard.server.common.data.device.profile.MqttProtoDeviceProfileTransportConfiguration;
|
||||
import org.thingsboard.server.common.data.security.Authority;
|
||||
import org.thingsboard.server.common.data.security.DeviceCredentials;
|
||||
import org.thingsboard.server.controller.AbstractControllerTest;
|
||||
@ -190,8 +192,12 @@ public abstract class AbstractMqttIntegrationTest extends AbstractControllerTest
|
||||
deviceProfile.setDescription(transportPayloadType.name() + " Test");
|
||||
DeviceProfileData deviceProfileData = new DeviceProfileData();
|
||||
DefaultDeviceProfileConfiguration configuration = new DefaultDeviceProfileConfiguration();
|
||||
MqttDeviceProfileTransportConfiguration transportConfiguration = new MqttDeviceProfileTransportConfiguration();
|
||||
transportConfiguration.setTransportPayloadType(transportPayloadType);
|
||||
MqttDeviceProfileTransportConfiguration transportConfiguration;
|
||||
if (TransportPayloadType.JSON.equals(transportPayloadType)) {
|
||||
transportConfiguration = new MqttJsonDeviceProfileTransportConfiguration();
|
||||
} else {
|
||||
transportConfiguration = new MqttProtoDeviceProfileTransportConfiguration();
|
||||
}
|
||||
if (!StringUtils.isEmpty(telemetryTopic)) {
|
||||
transportConfiguration.setDeviceTelemetryTopic(telemetryTopic);
|
||||
}
|
||||
|
||||
@ -23,6 +23,7 @@ import org.eclipse.paho.client.mqttv3.MqttException;
|
||||
import org.eclipse.paho.client.mqttv3.MqttMessage;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.thingsboard.server.common.data.Device;
|
||||
import org.thingsboard.server.common.data.TransportPayloadType;
|
||||
@ -55,12 +56,14 @@ public abstract class AbstractMqttAttributesRequestProtoIntegrationTest extends
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testRequestAttributesValuesFromTheServer() throws Exception {
|
||||
processTestRequestAttributesValuesFromTheServer();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testRequestAttributesValuesFromTheServerGateway() throws Exception {
|
||||
processTestGatewayRequestAttributesValuesFromTheServer();
|
||||
}
|
||||
|
||||
@ -19,6 +19,7 @@ import com.google.protobuf.InvalidProtocolBufferException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.thingsboard.server.common.data.TransportPayloadType;
|
||||
import org.thingsboard.server.common.data.device.profile.MqttTopics;
|
||||
@ -47,11 +48,13 @@ public abstract class AbstractMqttAttributesUpdatesProtoIntegrationTest extends
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testSubscribeToAttributesUpdatesFromTheServer() throws Exception {
|
||||
processTestSubscribeToAttributesUpdates();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testSubscribeToAttributesUpdatesFromTheServerGateway() throws Exception {
|
||||
processGatewayTestSubscribeToAttributesUpdates();
|
||||
}
|
||||
|
||||
@ -46,21 +46,25 @@ public abstract class AbstractMqttServerSideRpcProtoIntegrationTest extends Abst
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testServerMqttOneWayRpc() throws Exception {
|
||||
processOneWayRpcTest();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testServerMqttTwoWayRpc() throws Exception {
|
||||
processTwoWayRpcTest();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testGatewayServerMqttOneWayRpc() throws Exception {
|
||||
processOneWayRpcTestGateway("Gateway Device OneWay RPC Proto");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testGatewayServerMqttTwoWayRpc() throws Exception {
|
||||
processTwoWayRpcTestGateway("Gateway Device TwoWay RPC Proto");
|
||||
}
|
||||
|
||||
@ -18,6 +18,7 @@ package org.thingsboard.server.mqtt.telemetry.attributes;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.thingsboard.server.common.data.TransportPayloadType;
|
||||
import org.thingsboard.server.gen.transport.TransportApiProtos;
|
||||
@ -46,6 +47,7 @@ public abstract class AbstractMqttAttributesProtoIntegrationTest extends Abstrac
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testPushMqttAttributes() throws Exception {
|
||||
List<String> expectedKeys = Arrays.asList("key1", "key2", "key3", "key4", "key5");
|
||||
TransportProtos.PostAttributeMsg msg = getPostAttributeMsg(expectedKeys);
|
||||
@ -53,6 +55,7 @@ public abstract class AbstractMqttAttributesProtoIntegrationTest extends Abstrac
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testPushMqttAttributesGateway() throws Exception {
|
||||
TransportApiProtos.GatewayAttributesMsg.Builder gatewayAttributesMsgProtoBuilder = TransportApiProtos.GatewayAttributesMsg.newBuilder();
|
||||
List<String> expectedKeys = Arrays.asList("key1", "key2", "key3", "key4", "key5");
|
||||
|
||||
@ -19,6 +19,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.eclipse.paho.client.mqttv3.MqttAsyncClient;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.thingsboard.server.common.data.Device;
|
||||
import org.thingsboard.server.common.data.TransportPayloadType;
|
||||
@ -48,6 +49,7 @@ public abstract class AbstractMqttTimeseriesProtoIntegrationTest extends Abstrac
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testPushMqttTelemetry() throws Exception {
|
||||
List<String> expectedKeys = Arrays.asList("key1", "key2", "key3", "key4", "key5");
|
||||
TransportProtos.TsKvListProto tsKvListProto = getTsKvListProto(expectedKeys, 0);
|
||||
@ -55,6 +57,7 @@ public abstract class AbstractMqttTimeseriesProtoIntegrationTest extends Abstrac
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testPushMqttTelemetryWithTs() throws Exception {
|
||||
List<String> expectedKeys = Arrays.asList("key1", "key2", "key3", "key4", "key5");
|
||||
TransportProtos.TsKvListProto tsKvListProto = getTsKvListProto(expectedKeys, 10000);
|
||||
@ -62,6 +65,7 @@ public abstract class AbstractMqttTimeseriesProtoIntegrationTest extends Abstrac
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testPushMqttTelemetryGateway() throws Exception {
|
||||
TransportApiProtos.GatewayTelemetryMsg.Builder gatewayTelemetryMsgProtoBuilder = TransportApiProtos.GatewayTelemetryMsg.newBuilder();
|
||||
List<String> expectedKeys = Arrays.asList("key1", "key2", "key3", "key4", "key5");
|
||||
@ -75,6 +79,7 @@ public abstract class AbstractMqttTimeseriesProtoIntegrationTest extends Abstrac
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testGatewayConnect() throws Exception {
|
||||
String deviceName = "Device A";
|
||||
TransportApiProtos.ConnectMsg connectMsgProto = getConnectProto(deviceName);
|
||||
|
||||
@ -71,6 +71,18 @@
|
||||
<artifactId>java-driver-core</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.squareup.wire</groupId>
|
||||
<artifactId>wire-schema</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.os72</groupId>
|
||||
<artifactId>protobuf-dynamic</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
||||
@ -29,7 +29,7 @@ import org.thingsboard.server.common.data.DeviceTransportType;
|
||||
property = "type")
|
||||
@JsonSubTypes({
|
||||
@JsonSubTypes.Type(value = DefaultDeviceProfileTransportConfiguration.class, name = "DEFAULT"),
|
||||
@JsonSubTypes.Type(value = MqttDeviceProfileTransportConfiguration.class, name = "MQTT"),
|
||||
@JsonSubTypes.Type(value = MqttDeviceProfileTransportConfiguration.class, name = "MQTT"),
|
||||
@JsonSubTypes.Type(value = Lwm2mDeviceProfileTransportConfiguration.class, name = "LWM2M")})
|
||||
public interface DeviceProfileTransportConfiguration {
|
||||
|
||||
|
||||
@ -15,17 +15,40 @@
|
||||
*/
|
||||
package org.thingsboard.server.common.data.device.profile;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonSubTypes;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
import com.squareup.wire.schema.Location;
|
||||
import com.squareup.wire.schema.internal.parser.MessageElement;
|
||||
import com.squareup.wire.schema.internal.parser.ProtoFileElement;
|
||||
import com.squareup.wire.schema.internal.parser.ProtoParser;
|
||||
import com.squareup.wire.schema.internal.parser.TypeElement;
|
||||
import lombok.Data;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.thingsboard.server.common.data.TransportPayloadType;
|
||||
import org.thingsboard.server.common.data.DeviceTransportType;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
@Data
|
||||
public class MqttDeviceProfileTransportConfiguration implements DeviceProfileTransportConfiguration {
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
@JsonTypeInfo(
|
||||
use = JsonTypeInfo.Id.NAME,
|
||||
include = JsonTypeInfo.As.PROPERTY,
|
||||
property = "transportPayloadType")
|
||||
@JsonSubTypes({
|
||||
@JsonSubTypes.Type(value = MqttJsonDeviceProfileTransportConfiguration.class, name = "JSON"),
|
||||
@JsonSubTypes.Type(value = MqttProtoDeviceProfileTransportConfiguration.class, name = "PROTOBUF")})
|
||||
@JsonDeserialize(using = MqttTransportConfigurationDeserializer.class)
|
||||
public abstract class MqttDeviceProfileTransportConfiguration implements DeviceProfileTransportConfiguration {
|
||||
|
||||
private TransportPayloadType transportPayloadType = TransportPayloadType.JSON;
|
||||
protected String deviceTelemetryTopic = MqttTopics.DEVICE_TELEMETRY_TOPIC;
|
||||
protected String deviceAttributesTopic = MqttTopics.DEVICE_ATTRIBUTES_TOPIC;
|
||||
|
||||
private String deviceTelemetryTopic = MqttTopics.DEVICE_TELEMETRY_TOPIC;
|
||||
private String deviceAttributesTopic = MqttTopics.DEVICE_ATTRIBUTES_TOPIC;
|
||||
public abstract TransportPayloadType getTransportPayloadType();
|
||||
|
||||
@Override
|
||||
public DeviceTransportType getType() {
|
||||
|
||||
@ -0,0 +1,42 @@
|
||||
/**
|
||||
* Copyright © 2016-2020 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.device.profile;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonDeserializer;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.thingsboard.server.common.data.DeviceTransportType;
|
||||
import org.thingsboard.server.common.data.TransportPayloadType;
|
||||
|
||||
@Slf4j
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
@JsonDeserialize(using = JsonDeserializer.None.class)
|
||||
public class MqttJsonDeviceProfileTransportConfiguration extends MqttDeviceProfileTransportConfiguration{
|
||||
|
||||
@Override
|
||||
public DeviceTransportType getType() {
|
||||
return super.getType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TransportPayloadType getTransportPayloadType() {
|
||||
return TransportPayloadType.JSON;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,152 @@
|
||||
/**
|
||||
* Copyright © 2016-2020 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.device.profile;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.databind.JsonDeserializer;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
import com.github.os72.protobuf.dynamic.DynamicSchema;
|
||||
import com.github.os72.protobuf.dynamic.EnumDefinition;
|
||||
import com.github.os72.protobuf.dynamic.MessageDefinition;
|
||||
import com.google.protobuf.Descriptors;
|
||||
import com.google.protobuf.DynamicMessage;
|
||||
import com.squareup.wire.schema.Location;
|
||||
import com.squareup.wire.schema.internal.parser.EnumConstantElement;
|
||||
import com.squareup.wire.schema.internal.parser.EnumElement;
|
||||
import com.squareup.wire.schema.internal.parser.FieldElement;
|
||||
import com.squareup.wire.schema.internal.parser.MessageElement;
|
||||
import com.squareup.wire.schema.internal.parser.ProtoFileElement;
|
||||
import com.squareup.wire.schema.internal.parser.ProtoParser;
|
||||
import com.squareup.wire.schema.internal.parser.TypeElement;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.thingsboard.server.common.data.DeviceTransportType;
|
||||
import org.thingsboard.server.common.data.TransportPayloadType;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Slf4j
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
@JsonDeserialize(using = JsonDeserializer.None.class)
|
||||
public class MqttProtoDeviceProfileTransportConfiguration extends MqttDeviceProfileTransportConfiguration {
|
||||
|
||||
public static final Location LOCATION = new Location("", "", -1, -1);
|
||||
public static final String ATTRIBUTES_PROTO_SCHEMA = "attributes proto schema";
|
||||
public static final String TELEMETRY_PROTO_SCHEMA = "telemetry proto schema";
|
||||
|
||||
private String deviceTelemetryProtoSchema;
|
||||
private String deviceAttributesProtoSchema;
|
||||
|
||||
@JsonIgnore
|
||||
private Descriptors.Descriptor telemetryMsgDescriptor;
|
||||
|
||||
@JsonIgnore
|
||||
private Descriptors.Descriptor attributesMsgDescriptor;
|
||||
|
||||
@Override
|
||||
public DeviceTransportType getType() {
|
||||
return super.getType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TransportPayloadType getTransportPayloadType() {
|
||||
return TransportPayloadType.PROTOBUF;
|
||||
}
|
||||
|
||||
public void validateTransportProtoSchema(String schema, String schemaName) throws IllegalArgumentException {
|
||||
ProtoParser schemaParser = new ProtoParser(LOCATION, schema.toCharArray());
|
||||
ProtoFileElement protoFileElement;
|
||||
try {
|
||||
protoFileElement = schemaParser.readProtoFile();
|
||||
} catch (Exception e) {
|
||||
throw new IllegalArgumentException("Failed to parse: " + schemaName + " due to: " + e.getMessage());
|
||||
}
|
||||
List<TypeElement> types = protoFileElement.getTypes();
|
||||
if (!CollectionUtils.isEmpty(types)) {
|
||||
if (types.stream().noneMatch(typeElement -> typeElement instanceof MessageElement)) {
|
||||
throw new IllegalArgumentException("Invalid " + schemaName + " provided! At least one Message definition should exists!");
|
||||
}
|
||||
} else {
|
||||
throw new IllegalArgumentException("Invalid " + schemaName + " provided!");
|
||||
}
|
||||
}
|
||||
|
||||
public Descriptors.Descriptor getDynamicMessageDescriptor(String protoSchema, String schemaName) {
|
||||
ProtoFileElement protoFileElement = getTransportProtoSchema(protoSchema);
|
||||
DynamicSchema.Builder schemaBuilder = DynamicSchema.newBuilder();
|
||||
schemaBuilder.setName(schemaName);
|
||||
schemaBuilder.setPackage(!StringUtils.isEmpty(protoFileElement.getPackageName()) ?
|
||||
protoFileElement.getPackageName() : schemaName.toLowerCase());
|
||||
|
||||
List<TypeElement> types = protoFileElement.getTypes();
|
||||
|
||||
List<EnumElement> enumTypes = types.stream()
|
||||
.filter(typeElement -> typeElement instanceof EnumElement)
|
||||
.map(typeElement -> (EnumElement) typeElement)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
List<MessageElement> messageTypes = types.stream()
|
||||
.filter(typeElement -> typeElement instanceof MessageElement)
|
||||
.map(typeElement -> (MessageElement) typeElement)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (!CollectionUtils.isEmpty(enumTypes)) {
|
||||
enumTypes.forEach(enumElement -> {
|
||||
List<EnumConstantElement> enumElementTypeConstants = enumElement.getConstants();
|
||||
EnumDefinition.Builder enumDefinitionBuilder = EnumDefinition.newBuilder(enumElement.getName());
|
||||
if (!CollectionUtils.isEmpty(enumElementTypeConstants)) {
|
||||
enumElementTypeConstants.forEach(constantElement -> enumDefinitionBuilder.addValue(constantElement.getName(), constantElement.getTag()));
|
||||
}
|
||||
EnumDefinition enumDefinition = enumDefinitionBuilder.build();
|
||||
schemaBuilder.addEnumDefinition(enumDefinition);
|
||||
});
|
||||
}
|
||||
|
||||
if (!CollectionUtils.isEmpty(messageTypes)) {
|
||||
messageTypes.forEach(messageElement -> {
|
||||
List<FieldElement> messageElementFields = messageElement.getFields();
|
||||
MessageDefinition.Builder messageDefinitionBuilder = MessageDefinition.newBuilder(messageElement.getName());
|
||||
if (!CollectionUtils.isEmpty(messageElementFields)) {
|
||||
messageElementFields.forEach(fieldElement -> messageDefinitionBuilder.addField(fieldElement.getType(), fieldElement.getName(), fieldElement.getTag(), fieldElement.getDefaultValue()));
|
||||
}
|
||||
MessageDefinition messageDefinition = messageDefinitionBuilder.build();
|
||||
schemaBuilder.addMessageDefinition(messageDefinition);
|
||||
});
|
||||
MessageElement lastMsg = messageTypes.stream().reduce((previous, last) -> last).get();
|
||||
try {
|
||||
DynamicSchema dynamicSchema = schemaBuilder.build();
|
||||
DynamicMessage.Builder builder = dynamicSchema.newMessageBuilder(lastMsg.getName());
|
||||
return builder.getDescriptorForType();
|
||||
} catch (Descriptors.DescriptorValidationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
} else {
|
||||
throw new RuntimeException("Failed to get Message Descriptor! Message types is empty for " + schemaName + " schema!");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private ProtoFileElement getTransportProtoSchema(String protoSchema) {
|
||||
return new ProtoParser(LOCATION, protoSchema.toCharArray()).readProtoFile();
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,50 @@
|
||||
/**
|
||||
* Copyright © 2016-2020 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.device.profile;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.DeserializationContext;
|
||||
import com.fasterxml.jackson.databind.JsonDeserializer;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@Slf4j
|
||||
public class MqttTransportConfigurationDeserializer extends StdDeserializer<MqttDeviceProfileTransportConfiguration> {
|
||||
|
||||
public MqttTransportConfigurationDeserializer() {
|
||||
super(MqttDeviceProfileTransportConfiguration.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MqttDeviceProfileTransportConfiguration deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
|
||||
try {
|
||||
JsonNode jsonNode = jsonParser.readValueAsTree();
|
||||
if (jsonNode.has("deviceTelemetryProtoSchema") || jsonNode.has("deviceAttributesProtoSchema")) {
|
||||
return jsonParser.getCodec().treeToValue(jsonNode, MqttProtoDeviceProfileTransportConfiguration.class);
|
||||
} else {
|
||||
return jsonParser.getCodec().treeToValue(jsonNode, MqttJsonDeviceProfileTransportConfiguration.class);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.trace("Failed to deserialize JSON content into equivalent tree model during creating {}!", MqttDeviceProfileTransportConfiguration.class.getSimpleName(), e);
|
||||
throw new RuntimeException("Failed to deserialize JSON content into equivalent tree model during creating " + MqttDeviceProfileTransportConfiguration.class.getSimpleName() + "!", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -208,24 +208,24 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
|
||||
|
||||
private void processDevicePublish(ChannelHandlerContext ctx, MqttPublishMessage mqttMsg, String topicName, int msgId) {
|
||||
try {
|
||||
MqttTransportAdaptor payloadAdaptor = deviceSessionCtx.getPayloadAdaptor();
|
||||
MqttTransportAdaptor adaptor = deviceSessionCtx.getPayloadAdaptor();
|
||||
if (deviceSessionCtx.isDeviceTelemetryTopic(topicName)) {
|
||||
TransportProtos.PostTelemetryMsg postTelemetryMsg = payloadAdaptor.convertToPostTelemetry(deviceSessionCtx, mqttMsg);
|
||||
TransportProtos.PostTelemetryMsg postTelemetryMsg = adaptor.convertToPostTelemetry(deviceSessionCtx, mqttMsg);
|
||||
transportService.process(deviceSessionCtx.getSessionInfo(), postTelemetryMsg, getPubAckCallback(ctx, msgId, postTelemetryMsg));
|
||||
} else if (deviceSessionCtx.isDeviceAttributesTopic(topicName)) {
|
||||
TransportProtos.PostAttributeMsg postAttributeMsg = payloadAdaptor.convertToPostAttributes(deviceSessionCtx, mqttMsg);
|
||||
TransportProtos.PostAttributeMsg postAttributeMsg = adaptor.convertToPostAttributes(deviceSessionCtx, mqttMsg);
|
||||
transportService.process(deviceSessionCtx.getSessionInfo(), postAttributeMsg, getPubAckCallback(ctx, msgId, postAttributeMsg));
|
||||
} else if (topicName.startsWith(MqttTopics.DEVICE_ATTRIBUTES_REQUEST_TOPIC_PREFIX)) {
|
||||
TransportProtos.GetAttributeRequestMsg getAttributeMsg = payloadAdaptor.convertToGetAttributes(deviceSessionCtx, mqttMsg);
|
||||
TransportProtos.GetAttributeRequestMsg getAttributeMsg = adaptor.convertToGetAttributes(deviceSessionCtx, mqttMsg);
|
||||
transportService.process(deviceSessionCtx.getSessionInfo(), getAttributeMsg, getPubAckCallback(ctx, msgId, getAttributeMsg));
|
||||
} else if (topicName.startsWith(MqttTopics.DEVICE_RPC_RESPONSE_TOPIC)) {
|
||||
TransportProtos.ToDeviceRpcResponseMsg rpcResponseMsg = payloadAdaptor.convertToDeviceRpcResponse(deviceSessionCtx, mqttMsg);
|
||||
TransportProtos.ToDeviceRpcResponseMsg rpcResponseMsg = adaptor.convertToDeviceRpcResponse(deviceSessionCtx, mqttMsg);
|
||||
transportService.process(deviceSessionCtx.getSessionInfo(), rpcResponseMsg, getPubAckCallback(ctx, msgId, rpcResponseMsg));
|
||||
} else if (topicName.startsWith(MqttTopics.DEVICE_RPC_REQUESTS_TOPIC)) {
|
||||
TransportProtos.ToServerRpcRequestMsg rpcRequestMsg = payloadAdaptor.convertToServerRpcRequest(deviceSessionCtx, mqttMsg);
|
||||
TransportProtos.ToServerRpcRequestMsg rpcRequestMsg = adaptor.convertToServerRpcRequest(deviceSessionCtx, mqttMsg);
|
||||
transportService.process(deviceSessionCtx.getSessionInfo(), rpcRequestMsg, getPubAckCallback(ctx, msgId, rpcRequestMsg));
|
||||
} else if (topicName.equals(MqttTopics.DEVICE_CLAIM_TOPIC)) {
|
||||
TransportProtos.ClaimDeviceMsg claimDeviceMsg = payloadAdaptor.convertToClaimDevice(deviceSessionCtx, mqttMsg);
|
||||
TransportProtos.ClaimDeviceMsg claimDeviceMsg = adaptor.convertToClaimDevice(deviceSessionCtx, mqttMsg);
|
||||
transportService.process(deviceSessionCtx.getSessionInfo(), claimDeviceMsg, getPubAckCallback(ctx, msgId, claimDeviceMsg));
|
||||
} else {
|
||||
transportService.reportActivity(deviceSessionCtx.getSessionInfo());
|
||||
|
||||
@ -15,7 +15,11 @@
|
||||
*/
|
||||
package org.thingsboard.server.transport.mqtt.adaptors;
|
||||
|
||||
import com.google.gson.JsonParser;
|
||||
import com.google.protobuf.Descriptors;
|
||||
import com.google.protobuf.DynamicMessage;
|
||||
import com.google.protobuf.InvalidProtocolBufferException;
|
||||
import com.google.protobuf.util.JsonFormat;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufAllocator;
|
||||
import io.netty.buffer.UnpooledByteBufAllocator;
|
||||
@ -29,9 +33,11 @@ import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.thingsboard.server.common.data.device.profile.MqttTopics;
|
||||
import org.thingsboard.server.common.transport.adaptor.AdaptorException;
|
||||
import org.thingsboard.server.common.transport.adaptor.JsonConverter;
|
||||
import org.thingsboard.server.common.transport.adaptor.ProtoConverter;
|
||||
import org.thingsboard.server.gen.transport.TransportApiProtos;
|
||||
import org.thingsboard.server.gen.transport.TransportProtos;
|
||||
import org.thingsboard.server.transport.mqtt.session.DeviceSessionCtx;
|
||||
import org.thingsboard.server.transport.mqtt.session.MqttDeviceAwareSessionContext;
|
||||
|
||||
import java.util.Optional;
|
||||
@ -44,19 +50,27 @@ public class ProtoMqttAdaptor implements MqttTransportAdaptor {
|
||||
|
||||
@Override
|
||||
public TransportProtos.PostTelemetryMsg convertToPostTelemetry(MqttDeviceAwareSessionContext ctx, MqttPublishMessage inbound) throws AdaptorException {
|
||||
DeviceSessionCtx deviceSessionCtx = (DeviceSessionCtx) ctx;
|
||||
byte[] bytes = toBytes(inbound.payload());
|
||||
try {
|
||||
return ProtoConverter.convertToTelemetryProto(bytes);
|
||||
} catch (InvalidProtocolBufferException | IllegalArgumentException e) {
|
||||
Descriptors.Descriptor telemetryDynamicMsgDescriptor = deviceSessionCtx.getTelemetryDynamicMsgDescriptor();
|
||||
DynamicMessage dynamicMessage = DynamicMessage.parseFrom(telemetryDynamicMsgDescriptor, bytes);
|
||||
String stringMsg = JsonFormat.printer().includingDefaultValueFields().print(dynamicMessage);
|
||||
return JsonConverter.convertToTelemetryProto(new JsonParser().parse(stringMsg));
|
||||
} catch (Exception e) {
|
||||
throw new AdaptorException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TransportProtos.PostAttributeMsg convertToPostAttributes(MqttDeviceAwareSessionContext ctx, MqttPublishMessage inbound) throws AdaptorException {
|
||||
DeviceSessionCtx deviceSessionCtx = (DeviceSessionCtx) ctx;
|
||||
byte[] bytes = toBytes(inbound.payload());
|
||||
try {
|
||||
return ProtoConverter.validatePostAttributeMsg(bytes);
|
||||
Descriptors.Descriptor attributesDynamicMessage = deviceSessionCtx.getAttributesDynamicMessageDescriptor();
|
||||
DynamicMessage dynamicMessage = DynamicMessage.parseFrom(attributesDynamicMessage, bytes);
|
||||
String stringMsg = JsonFormat.printer().includingDefaultValueFields().print(dynamicMessage);
|
||||
return JsonConverter.convertToAttributesProto(new JsonParser().parse(stringMsg));
|
||||
} catch (InvalidProtocolBufferException | IllegalArgumentException e) {
|
||||
throw new AdaptorException(e);
|
||||
}
|
||||
|
||||
@ -15,6 +15,7 @@
|
||||
*/
|
||||
package org.thingsboard.server.transport.mqtt.session;
|
||||
|
||||
import com.google.protobuf.Descriptors;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@ -23,6 +24,7 @@ import org.thingsboard.server.common.data.DeviceTransportType;
|
||||
import org.thingsboard.server.common.data.TransportPayloadType;
|
||||
import org.thingsboard.server.common.data.device.profile.DeviceProfileTransportConfiguration;
|
||||
import org.thingsboard.server.common.data.device.profile.MqttDeviceProfileTransportConfiguration;
|
||||
import org.thingsboard.server.common.data.device.profile.MqttProtoDeviceProfileTransportConfiguration;
|
||||
import org.thingsboard.server.transport.mqtt.MqttTransportContext;
|
||||
import org.thingsboard.server.transport.mqtt.adaptors.MqttTransportAdaptor;
|
||||
import org.thingsboard.server.transport.mqtt.util.MqttTopicFilter;
|
||||
@ -49,6 +51,8 @@ public class DeviceSessionCtx extends MqttDeviceAwareSessionContext {
|
||||
private volatile MqttTopicFilter telemetryTopicFilter = MqttTopicFilterFactory.getDefaultTelemetryFilter();
|
||||
private volatile MqttTopicFilter attributesTopicFilter = MqttTopicFilterFactory.getDefaultAttributesFilter();
|
||||
private volatile TransportPayloadType payloadType = TransportPayloadType.JSON;
|
||||
private volatile Descriptors.Descriptor attributesDynamicMessageDescriptor;
|
||||
private volatile Descriptors.Descriptor telemetryDynamicMessageDescriptor;
|
||||
|
||||
public DeviceSessionCtx(UUID sessionId, ConcurrentMap<MqttTopicMatcher, Integer> mqttQoSMap, MqttTransportContext context) {
|
||||
super(sessionId, mqttQoSMap);
|
||||
@ -63,7 +67,9 @@ public class DeviceSessionCtx extends MqttDeviceAwareSessionContext {
|
||||
return msgIdSeq.incrementAndGet();
|
||||
}
|
||||
|
||||
public boolean isDeviceTelemetryTopic(String topicName) { return telemetryTopicFilter.filter(topicName); }
|
||||
public boolean isDeviceTelemetryTopic(String topicName) {
|
||||
return telemetryTopicFilter.filter(topicName);
|
||||
}
|
||||
|
||||
public boolean isDeviceAttributesTopic(String topicName) {
|
||||
return attributesTopicFilter.filter(topicName);
|
||||
@ -77,6 +83,14 @@ public class DeviceSessionCtx extends MqttDeviceAwareSessionContext {
|
||||
return payloadType.equals(TransportPayloadType.JSON);
|
||||
}
|
||||
|
||||
public Descriptors.Descriptor getTelemetryDynamicMsgDescriptor() {
|
||||
return telemetryDynamicMessageDescriptor;
|
||||
}
|
||||
|
||||
public Descriptors.Descriptor getAttributesDynamicMessageDescriptor() {
|
||||
return attributesDynamicMessageDescriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDeviceProfile(DeviceProfile deviceProfile) {
|
||||
super.setDeviceProfile(deviceProfile);
|
||||
@ -98,10 +112,14 @@ public class DeviceSessionCtx extends MqttDeviceAwareSessionContext {
|
||||
payloadType = mqttConfig.getTransportPayloadType();
|
||||
telemetryTopicFilter = MqttTopicFilterFactory.toFilter(mqttConfig.getDeviceTelemetryTopic());
|
||||
attributesTopicFilter = MqttTopicFilterFactory.toFilter(mqttConfig.getDeviceAttributesTopic());
|
||||
if (payloadType.equals(TransportPayloadType.PROTOBUF) && mqttConfig instanceof MqttProtoDeviceProfileTransportConfiguration) {
|
||||
MqttProtoDeviceProfileTransportConfiguration protoMqttConfig = (MqttProtoDeviceProfileTransportConfiguration) mqttConfig;
|
||||
telemetryDynamicMessageDescriptor = protoMqttConfig.getDynamicMessageDescriptor(protoMqttConfig.getDeviceTelemetryProtoSchema(), "telemetrySchema");
|
||||
attributesDynamicMessageDescriptor = protoMqttConfig.getDynamicMessageDescriptor(protoMqttConfig.getDeviceAttributesProtoSchema(), "attributesSchema");
|
||||
}
|
||||
} else {
|
||||
telemetryTopicFilter = MqttTopicFilterFactory.getDefaultTelemetryFilter();
|
||||
attributesTopicFilter = MqttTopicFilterFactory.getDefaultAttributesFilter();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
12
pom.xml
12
pom.xml
@ -106,6 +106,8 @@
|
||||
<commons-collections.version>3.2.2</commons-collections.version>
|
||||
<java-websocket.version>1.5.0</java-websocket.version>
|
||||
<micrometer.version>1.5.2</micrometer.version>
|
||||
<protobuf-dynamic.version>1.0.1</protobuf-dynamic.version>
|
||||
<wire-schema.version>3.4.0</wire-schema.version>
|
||||
</properties>
|
||||
|
||||
<modules>
|
||||
@ -1369,6 +1371,16 @@
|
||||
<artifactId>micrometer-registry-prometheus</artifactId>
|
||||
<version>${micrometer.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.os72</groupId>
|
||||
<artifactId>protobuf-dynamic</artifactId>
|
||||
<version>${protobuf-dynamic.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.squareup.wire</groupId>
|
||||
<artifactId>wire-schema</artifactId>
|
||||
<version>${wire-schema.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
|
||||
@ -20,17 +20,6 @@
|
||||
<fieldset class="fields-group">
|
||||
<legend class="group-title" translate>device-profile.mqtt-device-topic-filters</legend>
|
||||
<div fxLayoutGap="8px" fxLayout="column">
|
||||
<mat-form-field class="mat-block">
|
||||
<mat-label translate>device-profile.mqtt-device-payload-type</mat-label>
|
||||
<mat-select formControlName="transportPayloadType" required>
|
||||
<mat-option *ngFor="let type of mqttTransportPayloadTypes" [value]="type">
|
||||
{{mqttTransportPayloadTypeTranslations.get(type) | translate}}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
<mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('configuration.transportPayloadType').hasError('required')">
|
||||
{{ 'device-profile.mqtt-payload-type-required' | translate }}
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
<div fxLayout="row" fxLayoutGap="8px" fxLayout.xs="column">
|
||||
<mat-form-field fxFlex>
|
||||
<mat-label translate>device-profile.telemetry-topic-filter</mat-label>
|
||||
@ -68,5 +57,40 @@
|
||||
<div class="tb-hint" innerHTML="{{ 'device-profile.multi-level-wildcards-hint' | translate }}"></div>
|
||||
</div>
|
||||
</fieldset>
|
||||
<fieldset class="fields-group">
|
||||
<legend class="group-title" translate>device-profile.mqtt-device-payload-type</legend>
|
||||
<div fxLayoutGap="8px" fxLayout="column">
|
||||
<mat-form-field class="mat-block">
|
||||
<mat-select formControlName="transportPayloadType" required>
|
||||
<mat-option *ngFor="let type of mqttTransportPayloadTypes" [value]="type">
|
||||
{{mqttTransportPayloadTypeTranslations.get(type) | translate}}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
<mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('configuration.transportPayloadType').hasError('required')">
|
||||
{{ 'device-profile.mqtt-payload-type-required' | translate }}
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
<div *ngIf="protoPayloadType()" fxLayout="column">
|
||||
<mat-form-field fxFlex>
|
||||
<mat-label translate>device-profile.telemetry-proto-schema</mat-label>
|
||||
<textarea matInput required
|
||||
formControlName="deviceTelemetryProtoSchema"
|
||||
rows="5"></textarea>
|
||||
<mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('configuration.deviceTelemetryProtoSchema').hasError('required')">
|
||||
{{ 'device-profile.telemetry-proto-schema-required' | translate}}
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
<mat-form-field fxFlex>
|
||||
<mat-label translate>device-profile.attributes-proto-schema</mat-label>
|
||||
<textarea matInput required
|
||||
formControlName="deviceAttributesProtoSchema"
|
||||
rows="5"></textarea>
|
||||
<mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('configuration.deviceAttributesProtoSchema').hasError('required')">
|
||||
{{ 'device-profile.attributes-proto-schema-required' | translate}}
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</section>
|
||||
</form>
|
||||
|
||||
@ -28,12 +28,13 @@ import { Store } from '@ngrx/store';
|
||||
import { AppState } from '@app/core/core.state';
|
||||
import { coerceBooleanProperty } from '@angular/cdk/coercion';
|
||||
import {
|
||||
MqttTransportPayloadType,
|
||||
DeviceProfileTransportConfiguration,
|
||||
DeviceTransportType,
|
||||
MqttDeviceProfileTransportConfiguration, mqttTransportPayloadTypeTranslationMap
|
||||
MqttDeviceProfileTransportConfiguration,
|
||||
MqttTransportPayloadType,
|
||||
mqttTransportPayloadTypeTranslationMap
|
||||
} from '@shared/models/device.models';
|
||||
import { isDefinedAndNotNull } from '@core/utils';
|
||||
import {isDefinedAndNotNull} from '@core/utils';
|
||||
|
||||
@Component({
|
||||
selector: 'tb-mqtt-device-profile-transport-configuration',
|
||||
@ -86,7 +87,9 @@ export class MqttDeviceProfileTransportConfigurationComponent implements Control
|
||||
configuration: this.fb.group({
|
||||
deviceAttributesTopic: [null, [Validators.required, this.validationMQTTTopic()]],
|
||||
deviceTelemetryTopic: [null, [Validators.required, this.validationMQTTTopic()]],
|
||||
transportPayloadType: [MqttTransportPayloadType.JSON, Validators.required]
|
||||
transportPayloadType: [MqttTransportPayloadType.JSON, Validators.required],
|
||||
// deviceTelemetryProtoSchema: [null, Validators.required],
|
||||
// deviceAttributesProtoSchema: [null, Validators.required]
|
||||
})
|
||||
});
|
||||
this.mqttDeviceProfileTransportConfigurationFormGroup.valueChanges.subscribe(() => {
|
||||
@ -103,6 +106,11 @@ export class MqttDeviceProfileTransportConfigurationComponent implements Control
|
||||
}
|
||||
}
|
||||
|
||||
protoPayloadType(): boolean {
|
||||
let configuration = this.mqttDeviceProfileTransportConfigurationFormGroup.getRawValue().configuration;
|
||||
return configuration.transportPayloadType === MqttTransportPayloadType.PROTOBUF;
|
||||
}
|
||||
|
||||
writeValue(value: MqttDeviceProfileTransportConfiguration | null): void {
|
||||
if (isDefinedAndNotNull(value)) {
|
||||
this.mqttDeviceProfileTransportConfigurationFormGroup.patchValue({configuration: value}, {emitEvent: false});
|
||||
@ -114,6 +122,14 @@ export class MqttDeviceProfileTransportConfigurationComponent implements Control
|
||||
if (this.mqttDeviceProfileTransportConfigurationFormGroup.valid) {
|
||||
configuration = this.mqttDeviceProfileTransportConfigurationFormGroup.getRawValue().configuration;
|
||||
configuration.type = DeviceTransportType.MQTT;
|
||||
let configurationFormGroup = this.mqttDeviceProfileTransportConfigurationFormGroup.controls.configuration as FormGroup;
|
||||
if (configuration.transportPayloadType === MqttTransportPayloadType.PROTOBUF) {
|
||||
configurationFormGroup.addControl('deviceTelemetryProtoSchema', this.fb.control(null, Validators.required));
|
||||
configurationFormGroup.addControl('deviceAttributesProtoSchema', this.fb.control(null, Validators.required));
|
||||
} else {
|
||||
configurationFormGroup.removeControl('deviceTelemetryProtoSchema');
|
||||
configurationFormGroup.removeControl('deviceAttributesProtoSchema');
|
||||
}
|
||||
}
|
||||
this.propagateChange(configuration);
|
||||
}
|
||||
|
||||
@ -807,6 +807,10 @@
|
||||
"telemetry-topic-filter-required": "Telemetry topic filter is required.",
|
||||
"attributes-topic-filter": "Attributes topic filter",
|
||||
"attributes-topic-filter-required": "Attributes topic filter is required.",
|
||||
"telemetry-proto-schema": "Telemetry proto schema",
|
||||
"telemetry-proto-schema-required": "Telemetry proto schema is required.",
|
||||
"attributes-proto-schema": "Attributes proto schema",
|
||||
"attributes-proto-schema-required": "Attributes proto schema is required.",
|
||||
"rpc-response-topic-filter": "RPC response topic filter",
|
||||
"rpc-response-topic-filter-required": "RPC response topic filter is required.",
|
||||
"not-valid-pattern-topic-filter": "Not valid pattern topic filter",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user