io.kestra.plugin.mqtt.services.MqttV3Service Maven / Gradle / Ivy
package io.kestra.plugin.mqtt.services;
import com.google.common.primitives.Ints;
import io.kestra.core.runners.RunContext;
import io.kestra.plugin.mqtt.AbstractMqttConnection;
import io.kestra.plugin.mqtt.Publish;
import io.kestra.plugin.mqtt.Subscribe;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.paho.client.mqttv3.*;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import javax.net.ssl.SSLSocketFactory;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.function.Consumer;
public class MqttV3Service implements MqttInterface {
MqttAsyncClient client;
@Getter
@Setter
private String crt;
@Override
public void connect(RunContext runContext, AbstractMqttConnection connection) throws Exception {
try {
client = new MqttAsyncClient(
runContext.render(connection.getServer()),
runContext.render(connection.getClientId()),
new MemoryPersistence()
);
org.eclipse.paho.client.mqttv3.MqttConnectOptions connectOptions = new org.eclipse.paho.client.mqttv3.MqttConnectOptions();
if (connection.getConnectionTimeout() != null) {
connectOptions.setConnectionTimeout((int) connection.getConnectionTimeout().toSeconds());
}
if (connection.getUsername() != null) {
connectOptions.setUserName(runContext.render(connection.getUsername()));
}
if (connection.getPassword() != null) {
connectOptions.setPassword(runContext.render(connection.getPassword()).toCharArray());
}
if (!StringUtils.isBlank(crt) && Path.of(crt).toFile().exists()) {
SSLSocketFactory socketFactory = CustomSSLSocketFactory.createSSLSocketFactory(crt);
connectOptions.setCleanSession(true);
connectOptions.setConnectionTimeout(60);
connectOptions.setKeepAliveInterval(60);
connectOptions.setSocketFactory(socketFactory);
}
if (connection.getHttpsHostnameVerificationEnabled() != null) {
connectOptions.setHttpsHostnameVerificationEnabled(connection.getHttpsHostnameVerificationEnabled());
}
IMqttToken connect = client.connect(connectOptions);
connect.waitForCompletion();
} catch (MqttException e) {
throw new Exception(e.getMessage(), e);
}
}
@SuppressWarnings("DuplicatedCode")
@Override
public void publish(RunContext runContext, Publish publish, byte[] message) throws Exception {
MqttMessage mqttMessage = new MqttMessage();
mqttMessage.setPayload(message);
mqttMessage.setRetained(publish.getRetain());
mqttMessage.setQos(publish.getQos());
try {
IMqttToken token = client.publish(runContext.render(publish.getTopic()), mqttMessage);
token.waitForCompletion();
} catch (MqttException e) {
throw new Exception(e.getMessage(), e);
}
}
@Override
public void subscribe(RunContext runContext, Subscribe subscribe, Consumer consumer) throws Exception {
String[] topics = subscribe.topics(runContext);
IMqttMessageListener messageListener = (topic, message) -> {
try {
consumer.accept(Message.builder()
.topic(topic)
.id(message.getId())
.qos(message.getQos())
.payload(subscribe.getSerdeType().deserialize(message.getPayload()))
.retain(message.isRetained())
.build());
} catch (Exception e) {
runContext.logger().error(
"Cannot process message {id: {}} from topic '{}'. Cause: {}",
message.getId(),
topic,
e.getMessage()
);
throw e;
}
};
IMqttMessageListener[] listeners = new IMqttMessageListener[topics.length];
Arrays.fill(listeners, messageListener);
ArrayList qos = new ArrayList<>();
for (int i = 0; i < topics.length; i++) {
qos.add(subscribe.getQos());
}
client.subscribe(topics, Ints.toArray(qos), listeners);
}
@Override
public void unsubscribe(RunContext runContext, Subscribe subscribe) throws Exception {
IMqttToken unsubscribe = client.unsubscribe(subscribe.topics(runContext));
unsubscribe.waitForCompletion();
}
@Override
public void onDisconnected(final Consumer handler) {
client.setCallback(new MqttCallback() {
@Override
public void connectionLost(Throwable cause) {
handler.accept(cause);
}
@Override
public void messageArrived(String topic, MqttMessage message) {
}
@Override
public void deliveryComplete(IMqttDeliveryToken token) {
}
});
}
@Override
public void close() throws Exception {
try {
this.client.disconnect();
this.client.close();
} catch (MqttException e) {
throw new Exception(e.getMessage(), e);
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy