Dark Sorrow
Dark Sorrow

Reputation: 1947

MQTT Paho Client does not reconnect automatically to broker

My paho-mqtt service is unable to reconnect to broker in case connection is lost.
On connection lost I pinged both broker from the Android Client using adb shell and Android device from the server (Windows 10) hosting mosquito broker.
I connected to network using LAN via my Raspberry Pi 3B having deployed Android Things (latest version). The LAN network is quite stable. For Paho MQTT I am using latest version.
I have noticed that my MQTT connection is lost at random.

fun connect(context: Context) {
    connectOptions.keepAliveInterval=30//seconds
    connectOptions.mqttVersion = MqttConnectOptions.MQTT_VERSION_3_1_1
    connectOptions.isAutomaticReconnect = true
    connectOptions.isCleanSession = false

    connectOptions.setWill(Global.HmiSrNo + "_out", "Disconnected".toByteArray(), 2, false)
    mqttAndroidClient = MqttAndroidClient(context, serverUri, clientId)
    try {
        val token = mqttAndroidClient.connect(connectOptions)
        token.actionCallback = object : IMqttActionListener {
            override fun onSuccess(asyncActionToken: IMqttToken)
            {
                subscribe(context)
                automicLight.set(true)
                issnackbarshown = true
                if(Global.connectivitylost)
                    wantToCloseDialog = true

            }
            override fun onFailure(asyncActionToken: IMqttToken, exception: Throwable) {
                //connectionStatus = false
                Log.i("Connection", "failure")
                // Give your callback on connection failure here
                exception.printStackTrace()
            }
        }
    } catch (e: MqttException) {
        // Give your callback on connection failure here
        e.printStackTrace()
    }
 }

Build.Grade

<service android:name="org.eclipse.paho.android.service.MqttService" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="com.google.android.things.permission.USE_PERIPHERAL_IO" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
implementation 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.2.5'
implementation 'org.eclipse.paho:org.eclipse.paho.android.service:1.1.1'
repositories {
    maven {
        url "https://repo.eclipse.org/content/repositories/paho-releases/"
    }
}

Upvotes: 3

Views: 1863

Answers (1)

Javier Refuerzo
Javier Refuerzo

Reputation: 409

The following is JAVA so you will need the kotlin conversions.

Without the error message it will be hard to debug. Override "connectionLost(Throwable cause)" from the MqttCallback interface. This will give you the error reason.

In my applications I implement both the IMqttActionListener and MqttCallback in a single class. Track whether the app called disconnect or was disconnected for another reason. If the app did not call disconnect Restart the connection process. One of the most common reasons I've seen in the past is Context is null which closes the connection and will not allow connection to restart. If using AndroidViewModel you can use the application context which should live longer than Activity Context.

public class Pg3MqttDelegate implements IMqttActionListener, MqttCallback {

....



/////////////////////// IMqttActionListener /////////////////////////////
////////////////////////////////////////////////////////////////////////

@Override
public void onSuccess(IMqttToken asyncActionToken) {
    Log.v(LOG_TAG, "onSuccess: " + asyncActionToken);
    viewModel.setMqttConnected(true);
}

@Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
    viewModel.setError(ErrorObject.getInstance("" + exception));
    Log.v(LOG_TAG, "onFailure: " + exception + ", " + asyncActionToken.getException());
}



/////////////////////////// MqttCallback ///////////////////////////////
////////////////////////////////////////////////////////////////////////


@Override
public void connectionLost(Throwable cause) {
    Log.v(LOG_TAG, "connection lost: " + cause);
    viewModel.setMqttConnected(false);
}

@Override
public void messageArrived(String topic, MqttMessage message) throws Exception {
    Log.v(LOG_TAG, "Id:" + message.getId() + ", message topic:" + topic +  ", message:" + message.toString());

    ....

}

@Override
public void deliveryComplete(IMqttDeliveryToken token) {
    //triggered when publish is completed
    try {
        Log.v(LOG_TAG, "deliveryComplete token:" + token.getMessage());
    } catch (MqttException e) {
        Log.v(LOG_TAG, "could not log deliveryComplete message");
    }
}

Upvotes: -1

Related Questions