package nl.sikken.bertrik.hab.ttn;

import java.nio.charset.StandardCharsets;

import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Listener process for receiving data from the TTN.
 */
public final class TtnListener {
    
    private static final Logger LOG = LoggerFactory.getLogger(TtnListener.class);
    private static final long DISCONNECT_TIMEOUT_MS = 3000;
    
    private static final String TOPIC = "+/devices/+/up";
    
    private final String clientId;
    private final IMessageReceived callback;
    private final String url;
    private final String appId;
    private final String appKey;
    private final String topic;

    private MqttClient mqttClient;

    /**
     * Constructor.
     * 
     * @param receiveCallback the interface for indicating a received message.
     * @param url the URL of the MQTT server
     * @param appId the user name
     * @param appKey the password
     */
    public TtnListener(IMessageReceived receiveCallback, String url, String appId, String appKey) {
        this.callback = receiveCallback;
        this.url = url;
        this.clientId = MqttClient.generateClientId();
        this.appId = appId;
        this.appKey = appKey;
        this.topic = TOPIC;
    }
    
    /**
     * Starts this module.
     * 
     * @throws MqttException in case something went wrong with MQTT 
     */
    public void start() throws MqttException {
        LOG.info("Starting TTN listener");
        
        // connect
        LOG.info("Connecting as user '{}' to MQTT server {}", appId, url);
        this.mqttClient = new MqttClient(url, clientId, new MemoryPersistence());
        final MqttConnectOptions options = new MqttConnectOptions();
        options.setUserName(appId);
        options.setPassword(appKey.toCharArray());
        options.setAutomaticReconnect(true);
        mqttClient.connect(options);
        
        // subscribe
        LOG.info("Subscribing to topic '{}'", topic);
        mqttClient.subscribe(topic, this::messageArrived);

        LOG.info("Started TTN listener");
    }
    
    /**
     * Handles an incoming message.
     * 
     * @param topic the topic
     * @param mqttMessage the message
     * @throws Exception who knows?
     */
    private void messageArrived(String topic, MqttMessage mqttMessage) throws Exception {
        final String message = new String(mqttMessage.getPayload(), StandardCharsets.US_ASCII);
        LOG.info("Message arrived on topic '{}': {}", topic, message);
        // forward it to our user
        callback.messageReceived(topic, message);
    }
    
    /**
     * Stops this module.
     */
    public void stop() {
        LOG.info("Stopping TTN listener");
        try {
            mqttClient.disconnect(DISCONNECT_TIMEOUT_MS);
        } catch (MqttException e) {
            // don't care, just log
            LOG.warn("Caught exception on disconnect: {}", e.getMessage());
        } finally {
            try {
                mqttClient.close();
            } catch (MqttException e) {
                // don't care, just log
                LOG.warn("Caught exception on close: {}", e.getMessage());
            }
        }
        LOG.info("Stopped TTN listener");
    }
    
}

@@ -2164,19 +2164,20 @@
 connect(
-tru
+fals
 e);%0D%0A   

Disable paho mqtt automatic reconnect, it doesn't work anyway. I prefer to stop with an exception rather than a silent failure.