Browse Source

Refactoring due to comments

pull/8186/head
Andrii Shvaika 4 years ago
parent
commit
3477ddac0f
  1. 12
      application/src/main/java/org/thingsboard/server/service/transport/DefaultTransportApiService.java
  2. 4
      application/src/test/java/org/thingsboard/server/transport/mqtt/AbstractMqttIntegrationTest.java
  3. 4
      application/src/test/java/org/thingsboard/server/transport/mqtt/MqttTestConfigProperties.java
  4. 6
      application/src/test/java/org/thingsboard/server/transport/mqtt/sparkplug/AbstractMqttV5ClientSparkplugTest.java
  5. 5
      application/src/test/java/org/thingsboard/server/transport/mqtt/sparkplug/attributes/AbstractMqttV5ClientSparkplugAttributesTest.java
  6. 4
      application/src/test/java/org/thingsboard/server/transport/mqtt/sparkplug/attributes/MqttV5ClientSparkplugBAttributesInProfileTest.java
  7. 1
      common/data/src/main/java/org/thingsboard/server/common/data/DataConstants.java
  8. 4
      common/data/src/main/java/org/thingsboard/server/common/data/device/profile/MqttDeviceProfileTransportConfiguration.java
  9. 40
      common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportHandler.java
  10. 48
      common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/AbstractGatewaySessionHandler.java
  11. 14
      common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/MqttDeviceAwareSessionContext.java
  12. 29
      common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/SparkplugDeviceSessionContext.java
  13. 37
      common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/SparkplugNodeSessionHandler.java
  14. 2
      common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/session/DeviceAwareSessionContext.java
  15. 12
      ui-ngx/src/app/modules/home/components/profile/device/mqtt-device-profile-transport-configuration.component.html
  16. 22
      ui-ngx/src/app/modules/home/components/profile/device/mqtt-device-profile-transport-configuration.component.ts
  17. 4
      ui-ngx/src/app/shared/models/device.models.ts

12
application/src/main/java/org/thingsboard/server/service/transport/DefaultTransportApiService.java

@ -47,8 +47,6 @@ import org.thingsboard.server.common.data.device.data.CoapDeviceTransportConfigu
import org.thingsboard.server.common.data.device.data.Lwm2mDeviceTransportConfiguration; import org.thingsboard.server.common.data.device.data.Lwm2mDeviceTransportConfiguration;
import org.thingsboard.server.common.data.device.data.PowerMode; import org.thingsboard.server.common.data.device.data.PowerMode;
import org.thingsboard.server.common.data.device.data.PowerSavingConfiguration; import org.thingsboard.server.common.data.device.data.PowerSavingConfiguration;
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.ProvisionDeviceProfileCredentials; import org.thingsboard.server.common.data.device.profile.ProvisionDeviceProfileCredentials;
import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.id.DeviceId;
@ -308,8 +306,7 @@ public class DefaultTransportApiService implements TransportApiService {
if (customerId != null && !customerId.isNullUid()) { if (customerId != null && !customerId.isNullUid()) {
metaData.putValue("customerId", customerId.toString()); metaData.putValue("customerId", customerId.toString());
} }
String deviceIdStr = requestMsg.getSparkplug() ? "sparkplugId" : "gatewayId"; metaData.putValue("gatewayId", gatewayId.toString());
metaData.putValue(deviceIdStr, gatewayId.toString());
DeviceId deviceId = device.getId(); DeviceId deviceId = device.getId();
ObjectNode entityNode = mapper.valueToTree(device); ObjectNode entityNode = mapper.valueToTree(device);
@ -320,12 +317,11 @@ public class DefaultTransportApiService implements TransportApiService {
if (deviceAdditionalInfo == null) { if (deviceAdditionalInfo == null) {
deviceAdditionalInfo = JacksonUtil.newObjectNode(); deviceAdditionalInfo = JacksonUtil.newObjectNode();
} }
String lastConnectedStr = requestMsg.getSparkplug() ? DataConstants.LAST_CONNECTED_SPARKPLUG : DataConstants.LAST_CONNECTED_GATEWAY;
if (deviceAdditionalInfo.isObject() && if (deviceAdditionalInfo.isObject() &&
(!deviceAdditionalInfo.has(lastConnectedStr) (!deviceAdditionalInfo.has(DataConstants.LAST_CONNECTED_GATEWAY)
|| !gatewayId.toString().equals(deviceAdditionalInfo.get(lastConnectedStr).asText()))) { || !gatewayId.toString().equals(deviceAdditionalInfo.get(DataConstants.LAST_CONNECTED_GATEWAY).asText()))) {
ObjectNode newDeviceAdditionalInfo = (ObjectNode) deviceAdditionalInfo; ObjectNode newDeviceAdditionalInfo = (ObjectNode) deviceAdditionalInfo;
newDeviceAdditionalInfo.put(lastConnectedStr, gatewayId.toString()); newDeviceAdditionalInfo.put(DataConstants.LAST_CONNECTED_GATEWAY, gatewayId.toString());
Device savedDevice = deviceService.saveDevice(device); Device savedDevice = deviceService.saveDevice(device);
tbClusterService.onDeviceUpdated(savedDevice, device); tbClusterService.onDeviceUpdated(savedDevice, device);
} }

4
application/src/test/java/org/thingsboard/server/transport/mqtt/AbstractMqttIntegrationTest.java

@ -103,8 +103,8 @@ public abstract class AbstractMqttIntegrationTest extends AbstractTransportInteg
if (StringUtils.hasLength(config.getAttributesTopicFilter())) { if (StringUtils.hasLength(config.getAttributesTopicFilter())) {
mqttDeviceProfileTransportConfiguration.setDeviceAttributesTopic(config.getAttributesTopicFilter()); mqttDeviceProfileTransportConfiguration.setDeviceAttributesTopic(config.getAttributesTopicFilter());
} }
mqttDeviceProfileTransportConfiguration.setSparkPlug(config.isSparkPlug()); mqttDeviceProfileTransportConfiguration.setSparkplug(config.isSparkplug());
mqttDeviceProfileTransportConfiguration.setSparkPlugAttributesMetricNames(config.sparkPlugAttributesMetricNames); mqttDeviceProfileTransportConfiguration.setSparkplugAttributesMetricNames(config.sparkplugAttributesMetricNames);
mqttDeviceProfileTransportConfiguration.setSendAckOnValidationException(config.isSendAckOnValidationException()); mqttDeviceProfileTransportConfiguration.setSendAckOnValidationException(config.isSendAckOnValidationException());
TransportPayloadTypeConfiguration transportPayloadTypeConfiguration; TransportPayloadTypeConfiguration transportPayloadTypeConfiguration;
if (TransportPayloadType.JSON.equals(transportPayloadType)) { if (TransportPayloadType.JSON.equals(transportPayloadType)) {

4
application/src/test/java/org/thingsboard/server/transport/mqtt/MqttTestConfigProperties.java

@ -28,8 +28,8 @@ public class MqttTestConfigProperties {
String deviceName; String deviceName;
String gatewayName; String gatewayName;
boolean isSparkPlug; boolean isSparkplug;
Set<String> sparkPlugAttributesMetricNames; Set<String> sparkplugAttributesMetricNames;
TransportPayloadType transportPayloadType; TransportPayloadType transportPayloadType;

6
application/src/test/java/org/thingsboard/server/transport/mqtt/sparkplug/AbstractMqttV5ClientSparkplugTest.java

@ -95,13 +95,13 @@ public abstract class AbstractMqttV5ClientSparkplugTest extends AbstractMqttInte
//*BIRTH //*BIRTH
protected static final MetricDataType metricBirthDataType_Int32 = Int32; protected static final MetricDataType metricBirthDataType_Int32 = Int32;
protected static final String metricBirthName_Int32 = "Device Metric int32"; protected static final String metricBirthName_Int32 = "Device Metric int32";
protected Set<String> sparkPlugAttributesMetricNames; protected Set<String> sparkplugAttributesMetricNames;
public void beforeSparkplugTest() throws Exception { public void beforeSparkplugTest() throws Exception {
MqttTestConfigProperties configProperties = MqttTestConfigProperties.builder() MqttTestConfigProperties configProperties = MqttTestConfigProperties.builder()
.gatewayName("Test Connect Sparkplug client node") .gatewayName("Test Connect Sparkplug client node")
.isSparkPlug(true) .isSparkplug(true)
.sparkPlugAttributesMetricNames(sparkPlugAttributesMetricNames) .sparkplugAttributesMetricNames(sparkplugAttributesMetricNames)
.transportPayloadType(TransportPayloadType.PROTOBUF) .transportPayloadType(TransportPayloadType.PROTOBUF)
.build(); .build();
processBeforeTest(configProperties); processBeforeTest(configProperties);

5
application/src/test/java/org/thingsboard/server/transport/mqtt/sparkplug/attributes/AbstractMqttV5ClientSparkplugAttributesTest.java

@ -41,11 +41,6 @@ import static org.thingsboard.server.transport.mqtt.util.sparkplug.SparkplugTopi
@Slf4j @Slf4j
public abstract class AbstractMqttV5ClientSparkplugAttributesTest extends AbstractMqttV5ClientSparkplugTest { public abstract class AbstractMqttV5ClientSparkplugAttributesTest extends AbstractMqttV5ClientSparkplugTest {
/**
* "sparkPlugAttributesMetricNames": ["SN node", "SN device", "Firmware version", "Date version", "Last date update"]
* @throws Exception
*/
protected void processClientWithCorrectAccessTokenPublishNCMDReBirth() throws Exception { protected void processClientWithCorrectAccessTokenPublishNCMDReBirth() throws Exception {
clientWithCorrectNodeAccessTokenWithNDEATH(); clientWithCorrectNodeAccessTokenWithNDEATH();
List<String> listKeys = connectionWithNBirth(metricBirthDataType_Int32, metricBirthName_Int32, nextInt32()); List<String> listKeys = connectionWithNBirth(metricBirthDataType_Int32, metricBirthName_Int32, nextInt32());

4
application/src/test/java/org/thingsboard/server/transport/mqtt/sparkplug/attributes/MqttV5ClientSparkplugBAttributesInProfileTest.java

@ -31,8 +31,8 @@ public class MqttV5ClientSparkplugBAttributesInProfileTest extends AbstractMqttV
@Before @Before
public void beforeTest() throws Exception { public void beforeTest() throws Exception {
sparkPlugAttributesMetricNames = new HashSet<>(); sparkplugAttributesMetricNames = new HashSet<>();
sparkPlugAttributesMetricNames.add(metricBirthName_Int32); sparkplugAttributesMetricNames.add(metricBirthName_Int32);
beforeSparkplugTest(); beforeSparkplugTest();
} }

1
common/data/src/main/java/org/thingsboard/server/common/data/DataConstants.java

@ -120,7 +120,6 @@ public class DataConstants {
public static final String MSG_SOURCE_KEY = "source"; public static final String MSG_SOURCE_KEY = "source";
public static final String LAST_CONNECTED_GATEWAY = "lastConnectedGateway"; public static final String LAST_CONNECTED_GATEWAY = "lastConnectedGateway";
public static final String LAST_CONNECTED_SPARKPLUG = "lastConnectedSparkplug";
public static final String MAIN_QUEUE_NAME = "Main"; public static final String MAIN_QUEUE_NAME = "Main";
public static final String MAIN_QUEUE_TOPIC = "tb_rule_engine.main"; public static final String MAIN_QUEUE_TOPIC = "tb_rule_engine.main";

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

@ -29,8 +29,8 @@ public class MqttDeviceProfileTransportConfiguration implements DeviceProfileTra
@NoXss @NoXss
private String deviceAttributesTopic = MqttTopics.DEVICE_ATTRIBUTES_TOPIC; private String deviceAttributesTopic = MqttTopics.DEVICE_ATTRIBUTES_TOPIC;
private TransportPayloadTypeConfiguration transportPayloadTypeConfiguration; private TransportPayloadTypeConfiguration transportPayloadTypeConfiguration;
private boolean sparkPlug; private boolean sparkplug;
private Set<String> sparkPlugAttributesMetricNames; private Set<String> sparkplugAttributesMetricNames;
private boolean sendAckOnValidationException; private boolean sendAckOnValidationException;
@Override @Override

40
common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportHandler.java

@ -392,21 +392,14 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
int msgId = mqttMsg.variableHeader().packetId(); int msgId = mqttMsg.variableHeader().packetId();
try { try {
SparkplugTopic sparkplugTopic = parseTopicPublish(topicName); SparkplugTopic sparkplugTopic = parseTopicPublish(topicName);
String deviceName = sparkplugTopic.isNode() ? deviceSessionCtx.getDeviceInfo().getDeviceName() : sparkplugTopic.getDeviceId();
if (sparkplugTopic.isNode()) { if (sparkplugTopic.isNode()) {
// A node topic // A node topic
SparkplugBProto.Payload sparkplugBProtoNode = SparkplugBProto.Payload.parseFrom(ProtoMqttAdaptor.toBytes(mqttMsg.payload())); SparkplugBProto.Payload sparkplugBProtoNode = SparkplugBProto.Payload.parseFrom(ProtoMqttAdaptor.toBytes(mqttMsg.payload()));
switch (sparkplugTopic.getType()) { switch (sparkplugTopic.getType()) {
case STATE:
// TODO
break;
case NBIRTH: case NBIRTH:
case NCMD: case NCMD:
case NDATA: case NDATA:
sparkplugSessionHandler.onAttributesTelemetryProto(msgId, sparkplugBProtoNode, deviceName, sparkplugTopic); sparkplugSessionHandler.onAttributesTelemetryProto(msgId, sparkplugBProtoNode, deviceSessionCtx.getDeviceInfo().getDeviceName(), sparkplugTopic);
break;
case NRECORD:
// TODO
break; break;
default: default:
} }
@ -414,30 +407,13 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
// A device topic // A device topic
SparkplugBProto.Payload sparkplugBProtoDevice = SparkplugBProto.Payload.parseFrom(ProtoMqttAdaptor.toBytes(mqttMsg.payload())); SparkplugBProto.Payload sparkplugBProtoDevice = SparkplugBProto.Payload.parseFrom(ProtoMqttAdaptor.toBytes(mqttMsg.payload()));
switch (sparkplugTopic.getType()) { switch (sparkplugTopic.getType()) {
case STATE:
// TODO
break;
case DBIRTH: case DBIRTH:
case DCMD: case DCMD:
case DDATA: case DDATA:
sparkplugSessionHandler.onAttributesTelemetryProto(msgId, sparkplugBProtoDevice, deviceName, sparkplugTopic); sparkplugSessionHandler.onAttributesTelemetryProto(msgId, sparkplugBProtoDevice, sparkplugTopic.getDeviceId(), sparkplugTopic);
break; break;
/**
* TODO
* 7.3.2. Device Death Certificate (DDEATH)
* The Sparkplug™ Topic Namespace for a device Death Certificate is:
* namespace/group_id/DDEATH/edge_node_id/device_id
* It is the responsibility of the MQTT EoN node to indicate the real-time state of either physical legacy device using
* poll/response protocols and/or local logical devices. If the device becomes unavailable for any reason (no
* response, CRC error, etc.) it is the responsibility of the EoN node to publish a DDEATH on behalf of the end device.
* Immediately upon reception of a DDEATH, any MQTT client subscribed to this device should set the data quality of
* all metrics to “STALE” and should note the time stamp when the DDEATH message was received.
*/
case DDEATH: case DDEATH:
sparkplugSessionHandler.onDeviceDisconnect(mqttMsg, deviceName); sparkplugSessionHandler.onDeviceDisconnect(mqttMsg, sparkplugTopic.getDeviceId());
break;
case DRECORD:
// TODO
break; break;
default: default:
} }
@ -1084,16 +1060,6 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
} }
} }
/**
* Sparkplug™ Specification Version 2.2
* 7.1.1. EoN Node Death Certificate (NDEATH)
* The Death Certificate topic for an MQTT EoN node is:
* namespace/group_id/NDEATH/edge_node_id
* The Death Certificate topic and payload described here are not “published” as an MQTT message by a client, but
* provided as parameters within the MQTT CONNECT control packet when this MQTT EoN node first establishes the
* MQTT Client session.
*/
private void checkSparkplugNodeSession(MqttConnectMessage connectMessage, ChannelHandlerContext ctx) { private void checkSparkplugNodeSession(MqttConnectMessage connectMessage, ChannelHandlerContext ctx) {
try { try {
if (sparkplugSessionHandler == null) { if (sparkplugSessionHandler == null) {

48
common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/AbstractGatewaySessionHandler.java

@ -83,7 +83,7 @@ import static org.thingsboard.server.transport.mqtt.util.sparkplug.SparkplugMess
* Created by ashvayka on 19.01.17. * Created by ashvayka on 19.01.17.
*/ */
@Slf4j @Slf4j
public abstract class AbstractGatewaySessionHandler { public abstract class AbstractGatewaySessionHandler<T extends AbstractGatewayDeviceSessionContext> {
protected static final String DEFAULT_DEVICE_TYPE = "default"; protected static final String DEFAULT_DEVICE_TYPE = "default";
private static final String CAN_T_PARSE_VALUE = "Can't parse value: "; private static final String CAN_T_PARSE_VALUE = "Can't parse value: ";
@ -94,8 +94,8 @@ public abstract class AbstractGatewaySessionHandler {
protected final TransportDeviceInfo gateway; protected final TransportDeviceInfo gateway;
protected final UUID sessionId; protected final UUID sessionId;
private final ConcurrentMap<String, Lock> deviceCreationLockMap; private final ConcurrentMap<String, Lock> deviceCreationLockMap;
private final ConcurrentMap<String, MqttDeviceAwareSessionContext> devices; private final ConcurrentMap<String, T> devices;
private final ConcurrentMap<String, ListenableFuture<MqttDeviceAwareSessionContext>> deviceFutures; private final ConcurrentMap<String, ListenableFuture<T>> deviceFutures;
protected final ConcurrentMap<MqttTopicMatcher, Integer> mqttQoSMap; protected final ConcurrentMap<MqttTopicMatcher, Integer> mqttQoSMap;
protected final ChannelHandlerContext channel; protected final ChannelHandlerContext channel;
protected final DeviceSessionCtx deviceSessionCtx; protected final DeviceSessionCtx deviceSessionCtx;
@ -206,9 +206,9 @@ public abstract class AbstractGatewaySessionHandler {
protected void processOnConnect(MqttPublishMessage msg, String deviceName, String deviceType) { protected void processOnConnect(MqttPublishMessage msg, String deviceName, String deviceType) {
log.trace("[{}] onDeviceConnect: {}", sessionId, deviceName); log.trace("[{}] onDeviceConnect: {}", sessionId, deviceName);
Futures.addCallback(onDeviceConnect(deviceName, deviceType), new FutureCallback<MqttDeviceAwareSessionContext>() { Futures.addCallback(onDeviceConnect(deviceName, deviceType), new FutureCallback<>() {
@Override @Override
public void onSuccess(@Nullable MqttDeviceAwareSessionContext result) { public void onSuccess(@Nullable T result) {
ack(msg, ReturnCode.SUCCESS); ack(msg, ReturnCode.SUCCESS);
log.trace("[{}] onDeviceConnectOk: {}", sessionId, deviceName); log.trace("[{}] onDeviceConnectOk: {}", sessionId, deviceName);
} }
@ -221,8 +221,8 @@ public abstract class AbstractGatewaySessionHandler {
}, context.getExecutor()); }, context.getExecutor());
} }
ListenableFuture<MqttDeviceAwareSessionContext> onDeviceConnect(String deviceName, String deviceType) { ListenableFuture<T> onDeviceConnect(String deviceName, String deviceType) {
MqttDeviceAwareSessionContext result = devices.get(deviceName); T result = devices.get(deviceName);
if (result == null) { if (result == null) {
Lock deviceCreationLock = deviceCreationLockMap.computeIfAbsent(deviceName, s -> new ReentrantLock()); Lock deviceCreationLock = deviceCreationLockMap.computeIfAbsent(deviceName, s -> new ReentrantLock());
deviceCreationLock.lock(); deviceCreationLock.lock();
@ -241,9 +241,9 @@ public abstract class AbstractGatewaySessionHandler {
} }
} }
private ListenableFuture<MqttDeviceAwareSessionContext> getDeviceCreationFuture(String deviceName, String deviceType) { private ListenableFuture<T> getDeviceCreationFuture(String deviceName, String deviceType) {
final SettableFuture<MqttDeviceAwareSessionContext> futureToSet = SettableFuture.create(); final SettableFuture<T> futureToSet = SettableFuture.create();
ListenableFuture<MqttDeviceAwareSessionContext> future = deviceFutures.putIfAbsent(deviceName, futureToSet); ListenableFuture<T> future = deviceFutures.putIfAbsent(deviceName, futureToSet);
if (future != null) { if (future != null) {
return future; return future;
} }
@ -258,7 +258,7 @@ public abstract class AbstractGatewaySessionHandler {
new TransportServiceCallback<>() { new TransportServiceCallback<>() {
@Override @Override
public void onSuccess(GetOrCreateDeviceFromGatewayResponse msg) { public void onSuccess(GetOrCreateDeviceFromGatewayResponse msg) {
AbstractGatewayDeviceSessionContext deviceSessionCtx = newDeviceSessionCtx(msg); T deviceSessionCtx = newDeviceSessionCtx(msg);
if (devices.putIfAbsent(deviceName, deviceSessionCtx) == null) { if (devices.putIfAbsent(deviceName, deviceSessionCtx) == null) {
log.trace("[{}] First got or created device [{}], type [{}] for the gateway session", sessionId, deviceName, deviceType); log.trace("[{}] First got or created device [{}], type [{}] for the gateway session", sessionId, deviceName, deviceType);
SessionInfoProto deviceSessionInfo = deviceSessionCtx.getSessionInfo(); SessionInfoProto deviceSessionInfo = deviceSessionCtx.getSessionInfo();
@ -288,7 +288,7 @@ public abstract class AbstractGatewaySessionHandler {
} }
} }
protected abstract AbstractGatewayDeviceSessionContext newDeviceSessionCtx(GetOrCreateDeviceFromGatewayResponse msg); protected abstract T newDeviceSessionCtx(GetOrCreateDeviceFromGatewayResponse msg);
protected int getMsgId(MqttPublishMessage mqttMsg) { protected int getMsgId(MqttPublishMessage mqttMsg) {
return mqttMsg.variableHeader().packetId(); return mqttMsg.variableHeader().packetId();
@ -341,7 +341,7 @@ public abstract class AbstractGatewaySessionHandler {
Futures.addCallback(checkDeviceConnected(deviceName), Futures.addCallback(checkDeviceConnected(deviceName),
new FutureCallback<>() { new FutureCallback<>() {
@Override @Override
public void onSuccess(@Nullable MqttDeviceAwareSessionContext deviceCtx) { public void onSuccess(@Nullable T deviceCtx) {
if (!deviceEntry.getValue().isJsonArray()) { if (!deviceEntry.getValue().isJsonArray()) {
throw new JsonSyntaxException(CAN_T_PARSE_VALUE + json); throw new JsonSyntaxException(CAN_T_PARSE_VALUE + json);
} }
@ -375,7 +375,7 @@ public abstract class AbstractGatewaySessionHandler {
Futures.addCallback(checkDeviceConnected(deviceName), Futures.addCallback(checkDeviceConnected(deviceName),
new FutureCallback<>() { new FutureCallback<>() {
@Override @Override
public void onSuccess(@Nullable MqttDeviceAwareSessionContext deviceCtx) { public void onSuccess(@Nullable T deviceCtx) {
TransportProtos.PostTelemetryMsg msg = telemetryMsg.getMsg(); TransportProtos.PostTelemetryMsg msg = telemetryMsg.getMsg();
try { try {
TransportProtos.PostTelemetryMsg postTelemetryMsg = ProtoConverter.validatePostTelemetryMsg(msg.toByteArray()); TransportProtos.PostTelemetryMsg postTelemetryMsg = ProtoConverter.validatePostTelemetryMsg(msg.toByteArray());
@ -425,7 +425,7 @@ public abstract class AbstractGatewaySessionHandler {
Futures.addCallback(checkDeviceConnected(deviceName), Futures.addCallback(checkDeviceConnected(deviceName),
new FutureCallback<>() { new FutureCallback<>() {
@Override @Override
public void onSuccess(@Nullable MqttDeviceAwareSessionContext deviceCtx) { public void onSuccess(@Nullable T deviceCtx) {
if (!deviceEntry.getValue().isJsonObject()) { if (!deviceEntry.getValue().isJsonObject()) {
throw new JsonSyntaxException(CAN_T_PARSE_VALUE + json); throw new JsonSyntaxException(CAN_T_PARSE_VALUE + json);
} }
@ -459,7 +459,7 @@ public abstract class AbstractGatewaySessionHandler {
Futures.addCallback(checkDeviceConnected(deviceName), Futures.addCallback(checkDeviceConnected(deviceName),
new FutureCallback<>() { new FutureCallback<>() {
@Override @Override
public void onSuccess(@Nullable MqttDeviceAwareSessionContext deviceCtx) { public void onSuccess(@Nullable T deviceCtx) {
TransportApiProtos.ClaimDevice claimRequest = claimDeviceMsg.getClaimRequest(); TransportApiProtos.ClaimDevice claimRequest = claimDeviceMsg.getClaimRequest();
if (claimRequest == null) { if (claimRequest == null) {
throw new IllegalArgumentException("Claim request for device: " + deviceName + " is null!"); throw new IllegalArgumentException("Claim request for device: " + deviceName + " is null!");
@ -501,7 +501,7 @@ public abstract class AbstractGatewaySessionHandler {
Futures.addCallback(checkDeviceConnected(deviceName), Futures.addCallback(checkDeviceConnected(deviceName),
new FutureCallback<>() { new FutureCallback<>() {
@Override @Override
public void onSuccess(@Nullable MqttDeviceAwareSessionContext deviceCtx) { public void onSuccess(@Nullable T deviceCtx) {
if (!deviceEntry.getValue().isJsonObject()) { if (!deviceEntry.getValue().isJsonObject()) {
throw new JsonSyntaxException(CAN_T_PARSE_VALUE + json); throw new JsonSyntaxException(CAN_T_PARSE_VALUE + json);
} }
@ -530,7 +530,7 @@ public abstract class AbstractGatewaySessionHandler {
Futures.addCallback(checkDeviceConnected(deviceName), Futures.addCallback(checkDeviceConnected(deviceName),
new FutureCallback<>() { new FutureCallback<>() {
@Override @Override
public void onSuccess(@Nullable MqttDeviceAwareSessionContext deviceCtx) { public void onSuccess(@Nullable T deviceCtx) {
TransportProtos.PostAttributeMsg kvListProto = attributesMsg.getMsg(); TransportProtos.PostAttributeMsg kvListProto = attributesMsg.getMsg();
if (kvListProto == null) { if (kvListProto == null) {
throw new IllegalArgumentException("Attributes List for device: " + deviceName + " is empty!"); throw new IllegalArgumentException("Attributes List for device: " + deviceName + " is empty!");
@ -609,7 +609,7 @@ public abstract class AbstractGatewaySessionHandler {
Futures.addCallback(checkDeviceConnected(deviceName), Futures.addCallback(checkDeviceConnected(deviceName),
new FutureCallback<>() { new FutureCallback<>() {
@Override @Override
public void onSuccess(@Nullable MqttDeviceAwareSessionContext deviceCtx) { public void onSuccess(@Nullable T deviceCtx) {
Integer requestId = jsonObj.get("id").getAsInt(); Integer requestId = jsonObj.get("id").getAsInt();
String data = jsonObj.get("data").toString(); String data = jsonObj.get("data").toString();
TransportProtos.ToDeviceRpcResponseMsg rpcResponseMsg = TransportProtos.ToDeviceRpcResponseMsg.newBuilder() TransportProtos.ToDeviceRpcResponseMsg rpcResponseMsg = TransportProtos.ToDeviceRpcResponseMsg.newBuilder()
@ -634,7 +634,7 @@ public abstract class AbstractGatewaySessionHandler {
Futures.addCallback(checkDeviceConnected(deviceName), Futures.addCallback(checkDeviceConnected(deviceName),
new FutureCallback<>() { new FutureCallback<>() {
@Override @Override
public void onSuccess(@Nullable MqttDeviceAwareSessionContext deviceCtx) { public void onSuccess(@Nullable T deviceCtx) {
Integer requestId = gatewayRpcResponseMsg.getId(); Integer requestId = gatewayRpcResponseMsg.getId();
String data = gatewayRpcResponseMsg.getData(); String data = gatewayRpcResponseMsg.getData();
TransportProtos.ToDeviceRpcResponseMsg rpcResponseMsg = TransportProtos.ToDeviceRpcResponseMsg.newBuilder() TransportProtos.ToDeviceRpcResponseMsg rpcResponseMsg = TransportProtos.ToDeviceRpcResponseMsg.newBuilder()
@ -661,7 +661,7 @@ public abstract class AbstractGatewaySessionHandler {
Futures.addCallback(checkDeviceConnected(deviceName), Futures.addCallback(checkDeviceConnected(deviceName),
new FutureCallback<>() { new FutureCallback<>() {
@Override @Override
public void onSuccess(@Nullable MqttDeviceAwareSessionContext deviceCtx) { public void onSuccess(@Nullable T deviceCtx) {
transportService.process(deviceCtx.getSessionInfo(), requestMsg, getPubAckCallback(channel, deviceName, msgId, requestMsg)); transportService.process(deviceCtx.getSessionInfo(), requestMsg, getPubAckCallback(channel, deviceName, msgId, requestMsg));
} }
@ -685,8 +685,8 @@ public abstract class AbstractGatewaySessionHandler {
return result.build(); return result.build();
} }
protected ListenableFuture<MqttDeviceAwareSessionContext> checkDeviceConnected(String deviceName) { protected ListenableFuture<T> checkDeviceConnected(String deviceName) {
MqttDeviceAwareSessionContext ctx = devices.get(deviceName); T ctx = devices.get(deviceName);
if (ctx == null) { if (ctx == null) {
log.debug("[{}] Missing device [{}] for the gateway session", sessionId, deviceName); log.debug("[{}] Missing device [{}] for the gateway session", sessionId, deviceName);
return onDeviceConnect(deviceName, DEFAULT_DEVICE_TYPE); return onDeviceConnect(deviceName, DEFAULT_DEVICE_TYPE);
@ -729,7 +729,6 @@ public abstract class AbstractGatewaySessionHandler {
private void deregisterSession(String deviceName, MqttDeviceAwareSessionContext deviceSessionCtx) { private void deregisterSession(String deviceName, MqttDeviceAwareSessionContext deviceSessionCtx) {
if (this.deviceSessionCtx.isSparkplug()) { if (this.deviceSessionCtx.isSparkplug()) {
// add Msg Telemetry: key STATE type: String value: OFFLINE ts: sparkplugBProto.getTimestamp()
sendSparkplugStateOnTelemetry(deviceSessionCtx.getSessionInfo(), sendSparkplugStateOnTelemetry(deviceSessionCtx.getSessionInfo(),
deviceSessionCtx.getDeviceInfo().getDeviceName(), OFFLINE, new Date().getTime()); deviceSessionCtx.getDeviceInfo().getDeviceName(), OFFLINE, new Date().getTime());
} }
@ -744,7 +743,6 @@ public abstract class AbstractGatewaySessionHandler {
keyValueProtoBuilder.setType(TransportProtos.KeyValueType.STRING_V); keyValueProtoBuilder.setType(TransportProtos.KeyValueType.STRING_V);
keyValueProtoBuilder.setStringV(connectionState.name()); keyValueProtoBuilder.setStringV(connectionState.name());
TransportProtos.PostTelemetryMsg postTelemetryMsg = postTelemetryMsgCreated(keyValueProtoBuilder.build(), ts); TransportProtos.PostTelemetryMsg postTelemetryMsg = postTelemetryMsgCreated(keyValueProtoBuilder.build(), ts);
transportService.process(sessionInfo, postTelemetryMsg, getPubAckCallback(channel, deviceName, -1, postTelemetryMsg)); transportService.process(sessionInfo, postTelemetryMsg, getPubAckCallback(channel, deviceName, -1, postTelemetryMsg));
} }

14
common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/MqttDeviceAwareSessionContext.java

@ -32,30 +32,16 @@ import java.util.stream.Collectors;
public abstract class MqttDeviceAwareSessionContext extends DeviceAwareSessionContext { public abstract class MqttDeviceAwareSessionContext extends DeviceAwareSessionContext {
private final ConcurrentMap<MqttTopicMatcher, Integer> mqttQoSMap; private final ConcurrentMap<MqttTopicMatcher, Integer> mqttQoSMap;
private Map<String, SparkplugBProto.Payload.Metric> deviceBirthMetrics;
public MqttDeviceAwareSessionContext(UUID sessionId, ConcurrentMap<MqttTopicMatcher, Integer> mqttQoSMap) { public MqttDeviceAwareSessionContext(UUID sessionId, ConcurrentMap<MqttTopicMatcher, Integer> mqttQoSMap) {
super(sessionId); super(sessionId);
this.mqttQoSMap = mqttQoSMap; this.mqttQoSMap = mqttQoSMap;
this.deviceBirthMetrics = null;
} }
public ConcurrentMap<MqttTopicMatcher, Integer> getMqttQoSMap() { public ConcurrentMap<MqttTopicMatcher, Integer> getMqttQoSMap() {
return mqttQoSMap; return mqttQoSMap;
} }
public Map<String, SparkplugBProto.Payload.Metric> getDeviceBirthMetrics() {
return deviceBirthMetrics;
}
public void setDeviceBirthMetrics(java.util.List<org.thingsboard.server.gen.transport.mqtt.SparkplugBProto.Payload.Metric> metrics) {
if (this.deviceBirthMetrics == null) {
this.deviceBirthMetrics = new ConcurrentHashMap<>();
}
this.deviceBirthMetrics.putAll(metrics.stream()
.collect(Collectors.toMap(metric -> metric.getName(), metric -> metric)));
}
public MqttQoS getQoSForTopic(String topic) { public MqttQoS getQoSForTopic(String topic) {
List<Integer> qosList = mqttQoSMap.entrySet() List<Integer> qosList = mqttQoSMap.entrySet()
.stream() .stream()

29
common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/SparkplugDeviceSessionContext.java

@ -23,19 +23,25 @@ import org.thingsboard.server.common.data.exception.ThingsboardException;
import org.thingsboard.server.common.transport.TransportService; import org.thingsboard.server.common.transport.TransportService;
import org.thingsboard.server.common.transport.auth.TransportDeviceInfo; import org.thingsboard.server.common.transport.auth.TransportDeviceInfo;
import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.gen.transport.TransportProtos;
import org.thingsboard.server.gen.transport.mqtt.SparkplugBProto;
import org.thingsboard.server.transport.mqtt.util.sparkplug.SparkplugMessageType; import org.thingsboard.server.transport.mqtt.util.sparkplug.SparkplugMessageType;
import org.thingsboard.server.transport.mqtt.util.sparkplug.SparkplugRpcRequestHeader; import org.thingsboard.server.transport.mqtt.util.sparkplug.SparkplugRpcRequestHeader;
import org.thingsboard.server.transport.mqtt.util.sparkplug.SparkplugTopic; import org.thingsboard.server.transport.mqtt.util.sparkplug.SparkplugTopic;
import java.util.Date; import java.util.Date;
import java.util.Map;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
import java.util.stream.Collectors;
import static org.thingsboard.server.transport.mqtt.util.sparkplug.SparkplugMetricUtil.getTsKvProto; import static org.thingsboard.server.transport.mqtt.util.sparkplug.SparkplugMetricUtil.getTsKvProto;
@Slf4j @Slf4j
public class SparkplugDeviceSessionContext extends AbstractGatewayDeviceSessionContext<SparkplugNodeSessionHandler> { public class SparkplugDeviceSessionContext extends AbstractGatewayDeviceSessionContext<SparkplugNodeSessionHandler> {
private final Map<String, SparkplugBProto.Payload.Metric> deviceBirthMetrics = new ConcurrentHashMap<>();
public SparkplugDeviceSessionContext(SparkplugNodeSessionHandler parent, public SparkplugDeviceSessionContext(SparkplugNodeSessionHandler parent,
TransportDeviceInfo deviceInfo, TransportDeviceInfo deviceInfo,
DeviceProfile deviceProfile, DeviceProfile deviceProfile,
@ -45,6 +51,16 @@ public class SparkplugDeviceSessionContext extends AbstractGatewayDeviceSessionC
super(parent, deviceInfo, deviceProfile, mqttQoSMap, transportService); super(parent, deviceInfo, deviceProfile, mqttQoSMap, transportService);
} }
public Map<String, SparkplugBProto.Payload.Metric> getDeviceBirthMetrics() {
return deviceBirthMetrics;
}
public void setDeviceBirthMetrics(java.util.List<org.thingsboard.server.gen.transport.mqtt.SparkplugBProto.Payload.Metric> metrics) {
this.deviceBirthMetrics.putAll(metrics.stream()
.collect(Collectors.toMap(SparkplugBProto.Payload.Metric::getName, metric -> metric)));
}
@Override @Override
public void onAttributeUpdate(UUID sessionId, TransportProtos.AttributeUpdateNotificationMsg notification) { public void onAttributeUpdate(UUID sessionId, TransportProtos.AttributeUpdateNotificationMsg notification) {
log.trace("[{}] Received attributes update notification to sparkplug device", sessionId); log.trace("[{}] Received attributes update notification to sparkplug device", sessionId);
@ -64,20 +80,7 @@ public class SparkplugDeviceSessionContext extends AbstractGatewayDeviceSessionC
public void onToDeviceRpcRequest(UUID sessionId, TransportProtos.ToDeviceRpcRequestMsg rpcRequest) { public void onToDeviceRpcRequest(UUID sessionId, TransportProtos.ToDeviceRpcRequestMsg rpcRequest) {
log.trace("[{}] Received RPC Request notification to sparkplug device", sessionId); log.trace("[{}] Received RPC Request notification to sparkplug device", sessionId);
try { try {
/**
* DCMD {"metricName":"MyDeviceMetricText","value":"MyNodeMetric05_String_Value"}
* DCMD {"metricName":"MyNodeMetric02_LongInt64","value":2814119464032075444}
* DCMD {"metricName":"MyNodeMetric03_Double","value":6336935578763180333}
* DCMD {"metricName":"MyNodeMetric04_Float","value":413.18222}
* DCMD {"metricName":"Node Control/Rebirth","value":false}
* DCMD {"metricName":"MyNodeMetric06_Json_Bytes", "value":[40,47,-49]}
*/
SparkplugMessageType messageType = SparkplugMessageType.parseMessageType(rpcRequest.getMethodName()); SparkplugMessageType messageType = SparkplugMessageType.parseMessageType(rpcRequest.getMethodName());
if (messageType == null) {
parent.sendErrorRpcResponse(sessionInfo, rpcRequest.getRequestId(),
ThingsboardErrorCode.INVALID_ARGUMENTS, "Unsupported SparkplugMessageType: " + rpcRequest.getMethodName() + rpcRequest.getParams());
return;
}
SparkplugRpcRequestHeader header = JacksonUtil.fromString(rpcRequest.getParams(), SparkplugRpcRequestHeader.class); SparkplugRpcRequestHeader header = JacksonUtil.fromString(rpcRequest.getParams(), SparkplugRpcRequestHeader.class);
header.setMessageType(messageType.name()); header.setMessageType(messageType.name());
TransportProtos.TsKvProto tsKvProto = getTsKvProto(header.getMetricName(), header.getValue(), new Date().getTime()); TransportProtos.TsKvProto tsKvProto = getTsKvProto(header.getMetricName(), header.getValue(), new Date().getTime());

37
common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/SparkplugNodeSessionHandler.java

@ -18,6 +18,7 @@ package org.thingsboard.server.transport.mqtt.session;
import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.gson.JsonParser; import com.google.gson.JsonParser;
import com.google.gson.JsonSyntaxException; import com.google.gson.JsonSyntaxException;
import com.google.protobuf.Descriptors; import com.google.protobuf.Descriptors;
@ -65,7 +66,7 @@ import static org.thingsboard.server.transport.mqtt.util.sparkplug.SparkplugTopi
* Created by nickAS21 on 12.12.22 * Created by nickAS21 on 12.12.22
*/ */
@Slf4j @Slf4j
public class SparkplugNodeSessionHandler extends AbstractGatewaySessionHandler { public class SparkplugNodeSessionHandler extends AbstractGatewaySessionHandler<SparkplugDeviceSessionContext> {
private final SparkplugTopic sparkplugTopicNode; private final SparkplugTopic sparkplugTopicNode;
private final Map<String, SparkplugBProto.Payload.Metric> nodeBirthMetrics; private final Map<String, SparkplugBProto.Payload.Metric> nodeBirthMetrics;
@ -81,7 +82,7 @@ public class SparkplugNodeSessionHandler extends AbstractGatewaySessionHandler {
public void setNodeBirthMetrics(java.util.List<org.thingsboard.server.gen.transport.mqtt.SparkplugBProto.Payload.Metric> metrics) { public void setNodeBirthMetrics(java.util.List<org.thingsboard.server.gen.transport.mqtt.SparkplugBProto.Payload.Metric> metrics) {
this.nodeBirthMetrics.putAll(metrics.stream() this.nodeBirthMetrics.putAll(metrics.stream()
.collect(Collectors.toMap(metric -> metric.getName(), metric -> metric))); .collect(Collectors.toMap(SparkplugBProto.Payload.Metric::getName, metric -> metric)));
} }
public Map<String, SparkplugBProto.Payload.Metric> getNodeBirthMetrics() { public Map<String, SparkplugBProto.Payload.Metric> getNodeBirthMetrics() {
@ -102,24 +103,28 @@ public class SparkplugNodeSessionHandler extends AbstractGatewaySessionHandler {
public void onAttributesTelemetryProto(int msgId, SparkplugBProto.Payload sparkplugBProto, String deviceName, SparkplugTopic topic) throws AdaptorException, ThingsboardException { public void onAttributesTelemetryProto(int msgId, SparkplugBProto.Payload sparkplugBProto, String deviceName, SparkplugTopic topic) throws AdaptorException, ThingsboardException {
checkDeviceName(deviceName); checkDeviceName(deviceName);
ListenableFuture<MqttDeviceAwareSessionContext> contextListenableFuture = topic.isNode() ?
Futures.immediateFuture(this.deviceSessionCtx) : onDeviceConnectProto(deviceName); ListenableFuture<MqttDeviceAwareSessionContext> contextListenableFuture;
try { if (topic.isNode()) {
if (topic.isType(NBIRTH) || topic.isType(DBIRTH)) {
// add Msg Telemetry: key STATE type: String value: ONLINE ts: sparkplugBProto.getTimestamp()
sendSparkplugStateOnTelemetry(contextListenableFuture.get().getSessionInfo(), deviceName, ONLINE,
sparkplugBProto.getTimestamp());
}
if (topic.isType(NBIRTH)) { if (topic.isType(NBIRTH)) {
sendSparkplugStateOnTelemetry(this.deviceSessionCtx.getSessionInfo(), deviceName, ONLINE,
sparkplugBProto.getTimestamp());
setNodeBirthMetrics(sparkplugBProto.getMetricsList()); setNodeBirthMetrics(sparkplugBProto.getMetricsList());
} else if (topic.isType(DBIRTH)) {
contextListenableFuture.get().setDeviceBirthMetrics(sparkplugBProto.getMetricsList());
} }
} catch (InterruptedException | ExecutionException e) { contextListenableFuture = Futures.immediateFuture(this.deviceSessionCtx);
log.error("Failed add Metrics or change SparkplugConnectionState. MessageType *BIRTH.", e); } else {
ListenableFuture<SparkplugDeviceSessionContext> deviceCtx = onDeviceConnectProto(deviceName);
contextListenableFuture = Futures.transform(deviceCtx, ctx -> {
if (topic.isType(DBIRTH)) {
sendSparkplugStateOnTelemetry(ctx.getSessionInfo(), deviceName, ONLINE,
sparkplugBProto.getTimestamp());
ctx.setDeviceBirthMetrics(sparkplugBProto.getMetricsList());
}
return ctx;
}, MoreExecutors.directExecutor());
} }
Set<String> attributesMetricNames = ((MqttDeviceProfileTransportConfiguration) deviceSessionCtx Set<String> attributesMetricNames = ((MqttDeviceProfileTransportConfiguration) deviceSessionCtx
.getDeviceProfile().getProfileData().getTransportConfiguration()).getSparkPlugAttributesMetricNames(); .getDeviceProfile().getProfileData().getTransportConfiguration()).getSparkplugAttributesMetricNames();
if (attributesMetricNames != null) { if (attributesMetricNames != null) {
List<TransportApiProtos.AttributesMsg> attributesMsgList = convertToPostAttributes(sparkplugBProto, attributesMetricNames, deviceName); List<TransportApiProtos.AttributesMsg> attributesMsgList = convertToPostAttributes(sparkplugBProto, attributesMetricNames, deviceName);
onDeviceAttributesProto(contextListenableFuture, msgId, attributesMsgList, deviceName); onDeviceAttributesProto(contextListenableFuture, msgId, attributesMsgList, deviceName);
@ -213,7 +218,7 @@ public class SparkplugNodeSessionHandler extends AbstractGatewaySessionHandler {
} }
} }
private ListenableFuture<MqttDeviceAwareSessionContext> onDeviceConnectProto(String deviceName) throws ThingsboardException { private ListenableFuture<SparkplugDeviceSessionContext> onDeviceConnectProto(String deviceName) throws ThingsboardException {
try { try {
String deviceType = this.gateway.getDeviceType() + "-node"; String deviceType = this.gateway.getDeviceType() + "-node";
return onDeviceConnect(deviceName, deviceType); return onDeviceConnect(deviceName, deviceType);

2
common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/session/DeviceAwareSessionContext.java

@ -87,7 +87,7 @@ public abstract class DeviceAwareSessionContext implements SessionContext {
public boolean isSparkplug() { public boolean isSparkplug() {
DeviceProfileTransportConfiguration transportConfiguration = this.deviceProfile.getProfileData().getTransportConfiguration(); DeviceProfileTransportConfiguration transportConfiguration = this.deviceProfile.getProfileData().getTransportConfiguration();
if (transportConfiguration instanceof MqttDeviceProfileTransportConfiguration) { if (transportConfiguration instanceof MqttDeviceProfileTransportConfiguration) {
return ((MqttDeviceProfileTransportConfiguration) transportConfiguration).isSparkPlug(); return ((MqttDeviceProfileTransportConfiguration) transportConfiguration).isSparkplug();
} else { } else {
return false; return false;
} }

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

@ -16,17 +16,17 @@
--> -->
<form [formGroup]="mqttDeviceProfileTransportConfigurationFormGroup" style="padding-top: 8px;"> <form [formGroup]="mqttDeviceProfileTransportConfigurationFormGroup" style="padding-top: 8px;">
<mat-checkbox formControlName="sparkPlug"> <mat-checkbox formControlName="sparkplug">
{{ 'device-profile.mqtt-device-topic-filters-spark-plug' | translate }} {{ 'device-profile.mqtt-device-topic-filters-spark-plug' | translate }}
</mat-checkbox> </mat-checkbox>
<div *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('sparkPlug').value" <div *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('sparkplug').value"
class="tb-hint" innerHTML="{{ 'device-profile.mqtt-device-topic-filters-spark-plug-hint' | translate }}"></div> class="tb-hint" innerHTML="{{ 'device-profile.mqtt-device-topic-filters-spark-plug-hint' | translate }}"></div>
<mat-form-field floatLabel="always" class="mat-block" style="padding-top: 8px;" <mat-form-field floatLabel="always" class="mat-block" style="padding-top: 8px;"
*ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('sparkPlug').value"> *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('sparkplug').value">
<mat-label translate>device-profile.mqtt-device-topic-filters-spark-plug-attribute-metric-names</mat-label> <mat-label translate>device-profile.mqtt-device-topic-filters-spark-plug-attribute-metric-names</mat-label>
<mat-chip-list #attrMetricNamesChipList formControlName="sparkPlugAttributesMetricNames"> <mat-chip-list #attrMetricNamesChipList formControlName="sparkplugAttributesMetricNames">
<mat-chip <mat-chip
*ngFor="let name of mqttDeviceProfileTransportConfigurationFormGroup.get('sparkPlugAttributesMetricNames').value;" *ngFor="let name of mqttDeviceProfileTransportConfigurationFormGroup.get('sparkplugAttributesMetricNames').value;"
(removed)="removeAttributeMetricName(name)"> (removed)="removeAttributeMetricName(name)">
{{name}} {{name}}
<mat-icon matChipRemove>close</mat-icon> <mat-icon matChipRemove>close</mat-icon>
@ -40,7 +40,7 @@
<mat-hint innerHTML="{{ 'device-profile.mqtt-device-topic-filters-spark-plug-attribute-metric-names-hint' | translate }}"></mat-hint> <mat-hint innerHTML="{{ 'device-profile.mqtt-device-topic-filters-spark-plug-attribute-metric-names-hint' | translate }}"></mat-hint>
</mat-form-field> </mat-form-field>
</form> </form>
<form [formGroup]="mqttDeviceProfileTransportConfigurationFormGroup" style="padding-bottom: 16px;" *ngIf="!mqttDeviceProfileTransportConfigurationFormGroup.get('sparkPlug').value"> <form [formGroup]="mqttDeviceProfileTransportConfigurationFormGroup" style="padding-bottom: 16px;" *ngIf="!mqttDeviceProfileTransportConfigurationFormGroup.get('sparkplug').value">
<fieldset class="fields-group"> <fieldset class="fields-group">
<legend class="group-title" translate>device-profile.mqtt-device-topic-filters</legend> <legend class="group-title" translate>device-profile.mqtt-device-topic-filters</legend>
<div fxLayoutGap="8px" fxLayout="column"> <div fxLayoutGap="8px" fxLayout="column">

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

@ -96,8 +96,8 @@ export class MqttDeviceProfileTransportConfigurationComponent implements Control
this.mqttDeviceProfileTransportConfigurationFormGroup = this.fb.group({ this.mqttDeviceProfileTransportConfigurationFormGroup = this.fb.group({
deviceAttributesTopic: [null, [Validators.required, this.validationMQTTTopic()]], deviceAttributesTopic: [null, [Validators.required, this.validationMQTTTopic()]],
deviceTelemetryTopic: [null, [Validators.required, this.validationMQTTTopic()]], deviceTelemetryTopic: [null, [Validators.required, this.validationMQTTTopic()]],
sparkPlug: [false], sparkplug: [false],
sparkPlugAttributesMetricNames: [null], sparkplugAttributesMetricNames: [null],
sendAckOnValidationException: [false, Validators.required], sendAckOnValidationException: [false, Validators.required],
transportPayloadTypeConfiguration: this.fb.group({ transportPayloadTypeConfiguration: this.fb.group({
transportPayloadType: [TransportPayloadType.JSON, Validators.required], transportPayloadType: [TransportPayloadType.JSON, Validators.required],
@ -123,13 +123,13 @@ export class MqttDeviceProfileTransportConfigurationComponent implements Control
.patchValue(false, {emitEvent: false}); .patchValue(false, {emitEvent: false});
} }
}); });
this.mqttDeviceProfileTransportConfigurationFormGroup.get('sparkPlug').valueChanges.pipe( this.mqttDeviceProfileTransportConfigurationFormGroup.get('sparkplug').valueChanges.pipe(
takeUntil(this.destroy$) takeUntil(this.destroy$)
).subscribe((value) => { ).subscribe((value) => {
if (value) { if (value) {
this.mqttDeviceProfileTransportConfigurationFormGroup.disable({emitEvent: false}); this.mqttDeviceProfileTransportConfigurationFormGroup.disable({emitEvent: false});
this.mqttDeviceProfileTransportConfigurationFormGroup.get('sparkPlug').enable({emitEvent: false}); this.mqttDeviceProfileTransportConfigurationFormGroup.get('sparkplug').enable({emitEvent: false});
this.mqttDeviceProfileTransportConfigurationFormGroup.get('sparkPlugAttributesMetricNames').enable({emitEvent: false}); this.mqttDeviceProfileTransportConfigurationFormGroup.get('sparkplugAttributesMetricNames').enable({emitEvent: false});
} else { } else {
this.mqttDeviceProfileTransportConfigurationFormGroup.enable({emitEvent: false}); this.mqttDeviceProfileTransportConfigurationFormGroup.enable({emitEvent: false});
} }
@ -152,7 +152,7 @@ export class MqttDeviceProfileTransportConfigurationComponent implements Control
this.mqttDeviceProfileTransportConfigurationFormGroup.disable({emitEvent: false}); this.mqttDeviceProfileTransportConfigurationFormGroup.disable({emitEvent: false});
} else { } else {
this.mqttDeviceProfileTransportConfigurationFormGroup.enable({emitEvent: false}); this.mqttDeviceProfileTransportConfigurationFormGroup.enable({emitEvent: false});
this.mqttDeviceProfileTransportConfigurationFormGroup.get('sparkPlug').updateValueAndValidity({onlySelf: true}); this.mqttDeviceProfileTransportConfigurationFormGroup.get('sparkplug').updateValueAndValidity({onlySelf: true});
} }
} }
@ -170,17 +170,17 @@ export class MqttDeviceProfileTransportConfigurationComponent implements Control
this.mqttDeviceProfileTransportConfigurationFormGroup.patchValue(value, {emitEvent: false}); this.mqttDeviceProfileTransportConfigurationFormGroup.patchValue(value, {emitEvent: false});
this.updateTransportPayloadBasedControls(value.transportPayloadTypeConfiguration?.transportPayloadType); this.updateTransportPayloadBasedControls(value.transportPayloadTypeConfiguration?.transportPayloadType);
if (!this.disabled) { if (!this.disabled) {
this.mqttDeviceProfileTransportConfigurationFormGroup.get('sparkPlug').updateValueAndValidity({onlySelf: true}); this.mqttDeviceProfileTransportConfigurationFormGroup.get('sparkplug').updateValueAndValidity({onlySelf: true});
} }
} }
} }
removeAttributeMetricName(name: string): void { removeAttributeMetricName(name: string): void {
const names: string[] = this.mqttDeviceProfileTransportConfigurationFormGroup.get('sparkPlugAttributesMetricNames').value; const names: string[] = this.mqttDeviceProfileTransportConfigurationFormGroup.get('sparkplugAttributesMetricNames').value;
const index = names.indexOf(name); const index = names.indexOf(name);
if (index >= 0) { if (index >= 0) {
names.splice(index, 1); names.splice(index, 1);
this.mqttDeviceProfileTransportConfigurationFormGroup.get('sparkPlugAttributesMetricNames').setValue(names); this.mqttDeviceProfileTransportConfigurationFormGroup.get('sparkplugAttributesMetricNames').setValue(names);
} }
} }
@ -189,13 +189,13 @@ export class MqttDeviceProfileTransportConfigurationComponent implements Control
let value = event.value; let value = event.value;
if ((value || '').trim()) { if ((value || '').trim()) {
value = value.trim(); value = value.trim();
let names: string[] = this.mqttDeviceProfileTransportConfigurationFormGroup.get('sparkPlugAttributesMetricNames').value; let names: string[] = this.mqttDeviceProfileTransportConfigurationFormGroup.get('sparkplugAttributesMetricNames').value;
if (!names || names.indexOf(value) === -1) { if (!names || names.indexOf(value) === -1) {
if (!names) { if (!names) {
names = []; names = [];
} }
names.push(value); names.push(value);
this.mqttDeviceProfileTransportConfigurationFormGroup.get('sparkPlugAttributesMetricNames').setValue(names, {emitEvent: true}); this.mqttDeviceProfileTransportConfigurationFormGroup.get('sparkplugAttributesMetricNames').setValue(names, {emitEvent: true});
} }
} }
if (input) { if (input) {

4
ui-ngx/src/app/shared/models/device.models.ts

@ -242,7 +242,7 @@ export interface DefaultDeviceProfileTransportConfiguration {
export interface MqttDeviceProfileTransportConfiguration { export interface MqttDeviceProfileTransportConfiguration {
deviceTelemetryTopic?: string; deviceTelemetryTopic?: string;
deviceAttributesTopic?: string; deviceAttributesTopic?: string;
sparkPlug?: boolean; sparkplug?: boolean;
sendAckOnValidationException?: boolean; sendAckOnValidationException?: boolean;
transportPayloadTypeConfiguration?: { transportPayloadTypeConfiguration?: {
transportPayloadType?: TransportPayloadType; transportPayloadType?: TransportPayloadType;
@ -360,7 +360,7 @@ export function createDeviceProfileTransportConfiguration(type: DeviceTransportT
const mqttTransportConfiguration: MqttDeviceProfileTransportConfiguration = { const mqttTransportConfiguration: MqttDeviceProfileTransportConfiguration = {
deviceTelemetryTopic: 'v1/devices/me/telemetry', deviceTelemetryTopic: 'v1/devices/me/telemetry',
deviceAttributesTopic: 'v1/devices/me/attributes', deviceAttributesTopic: 'v1/devices/me/attributes',
sparkPlug: false, sparkplug: false,
sendAckOnValidationException: false, sendAckOnValidationException: false,
transportPayloadTypeConfiguration: { transportPayloadTypeConfiguration: {
transportPayloadType: TransportPayloadType.JSON, transportPayloadType: TransportPayloadType.JSON,

Loading…
Cancel
Save