Saurabh Chauhan
Saurabh Chauhan

Reputation: 3211

Local broker (MQTT) based Publish/Subscribe using Android Application

In my current project, I am using MQTT local broker based implementation and setup using this link. The local broker based MQTT implementation is working perfectly.

At initially, I am using Node.js publisher and subscriber with this local broker to enable the exchange of messages and it works without internet connection also (as these devices are connected to the same network, mqtt API for local broker based implementation is like http://192.168.0.105).

Now, I would like to replace Node.js subscriber with Android application. My android application using mqtt paho library for communication and using mqtt APImqtt://test.mosquitto.org:1883. If I am using mqtt open broker i.e. mosquitto than Node.js publisher and Android application subscriber both are working properly (this case is talking about mosquitto based mqtt implementation using the API mqtt://test.mosquitto.org:1883).

Now, I want to use local broker based implementation in Android application. So I have to replace mqtt://test.mosquitto.org:1883 API with http://192.168.0.105 as I want to use local broker based mqtt implementation. When I use http://192.168.0.105 API in the android code and deploy to mobile device, it displays error that Unfortunately, Android Application has stopped in andoid application.

How to use local-broker based implementation in android application?

Additionally sharing the code of Node.js publisher and subscriber. Node.js publisher (local broker based implementation)

var mqtt = require('mqtt');
var client = mqtt.connect('http://192.168.0.105');
setInterval(function() {
var data = {
     "tempValue" : Math.random(),
     "unitOfMeasurement" : 'C'
     };
client.publish('tempMeasurement', JSON.stringify(data));
}, 5000);

Node.js subscriber (local broker based implementation)

var mqtt = require('mqtt');
var client = mqtt.connect('http://192.168.0.105');
client.subscribe('tempMeasurement'); 
client.on('message', function(topic, payload) {
       if (topic.toString() == "tempMeasurement") {  
       console.log("Mesage Received "+ payload.toString());
   }       
 });

Sharing code of MQTT Subscriber for better clarity:

package iotsuite.pubsubmiddleware;

import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.internal.MemoryPersistence;

public class MQTTSubscriber {

// URI for open MQTT broker
// public static final String BROKER_URL = "tcp://test.mosquitto.org:1883";
public static final String BROKER_URL = "mqtt://192.168.0.105";

private MqttClient client;

public MQTTSubscriber(PubSubMiddleware pubsub) {
    try {
        client = new MqttClient(BROKER_URL, MqttClient.generateClientId(),
                new MemoryPersistence());

        client.setCallback(new PushCallback(pubsub));
        client.connect();

    } catch (MqttException e) {
        e.printStackTrace();
    }
}

public void subscribe(String topicName) throws MqttException {

    client.subscribe(topicName);

    System.out.println("Subscribed. Topic: " + topicName);
}

}

and subscribing for tempMeasurement using following code:

package framework;

 import iotsuite.common.Logger;
 import iotsuite.pubsubmiddleware.PubSubMiddleware;
 import iotsuite.pubsubmiddleware.Subscriber;
 import iotsuite.semanticmodel.Device;
 import android.util.Log;
 import com.google.gson.Gson;
 import com.google.gson.JsonObject;
 import com.google.gson.JsonParser;

 public abstract class SmartHomeApp implements Runnable, Subscriber {

protected final PubSubMiddleware myPubSubMiddleware;
protected final Device myDeviceInfo;
Gson gson = new Gson();

public SmartHomeApp(PubSubMiddleware pubSubM, Device deviceInfo) {

    this.myPubSubMiddleware = pubSubM;
    this.myDeviceInfo = deviceInfo;
    postInitialize();

}

protected void postInitialize() {
    subscribeDisplayTemp();

}

@Override
public void notifyReceived(String eventName, Object arg) {
    try {

        if (eventName.equals("tempMeasurement")) {
            Logger.log(myDeviceInfo.getName(), "TempMonitoringApp",
                    "Notification Received tempMeasurement ");
            JsonObject jsonObject = new JsonParser().parse(arg.toString())
                    .getAsJsonObject();
            double tempValue = jsonObject.get("tempValue").getAsDouble();
            // double yahootempValue =
            // jsonObject.get("yahootempValue").getAsDouble();
            TempStruct tempStruct = new TempStruct(tempValue, "C");
            System.out.println("tempValue is " + tempValue
                    + " in framework");
            Log.i("tempValue", "tempValue is received in framework");
            onNewDisplayTempNotify(tempStruct);
        }

    } catch (Exception e) {
        e.printStackTrace();
    }
}

@Override
public void run() {
}

public abstract void onNewDisplayTempNotify(TempStruct arg);

public void subscribeDisplayTemp() {

    this.myPubSubMiddleware.subscribe(this, "tempMeasurement");
}

}

Using the above code, I would like to display the tempValue received from Node.js code to Android application. Error from Android is as follow:

01-04 23:03:26.786: E/AndroidRuntime(21793): FATAL EXCEPTION: main
01-04 23:03:26.786: E/AndroidRuntime(21793): Process: com.example.android,      PID: 21793
01-04 23:03:26.786: E/AndroidRuntime(21793): java.lang.RuntimeException:    Unable to start activity         ComponentInfo{com.example.android/com.example.android.MainActivity}:       java.lang.IllegalArgumentException
01-04 23:03:26.786: E/AndroidRuntime(21793):    at    android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2426)
01-04 23:03:26.786: E/AndroidRuntime(21793):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2490)
01-04 23:03:26.786: E/AndroidRuntime(21793):    at android.app.ActivityThread.-wrap11(ActivityThread.java)
01-04 23:03:26.786: E/AndroidRuntime(21793):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1354)
01-04 23:03:26.786: E/AndroidRuntime(21793):    at android.os.Handler.dispatchMessage(Handler.java:102)
01-04 23:03:26.786: E/AndroidRuntime(21793):    at android.os.Looper.loop(Looper.java:148)
01-04 23:03:26.786: E/AndroidRuntime(21793):    at android.app.ActivityThread.main(ActivityThread.java:5443)
01-04 23:03:26.786: E/AndroidRuntime(21793):    at java.lang.reflect.Method.invoke(Native Method)
01-04 23:03:26.786: E/AndroidRuntime(21793):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:728)
01-04 23:03:26.786: E/AndroidRuntime(21793):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
01-04 23:03:26.786: E/AndroidRuntime(21793): Caused by: java.lang.IllegalArgumentException
01-04 23:03:26.786: E/AndroidRuntime(21793):    at  org.eclipse.paho.client.mqttv3.MqttClient.validateURI(MqttClient.java:204)
01-04 23:03:26.786: E/AndroidRuntime(21793):    at org.eclipse.paho.client.mqttv3.MqttClient.<init>(MqttClient.java:175)
01-04 23:03:26.786: E/AndroidRuntime(21793):    at iotsuite.pubsubmiddleware.MQTTPublisher.<init>(MQTTPublisher.java:21)
01-04 23:03:26.786: E/AndroidRuntime(21793):    at iotsuite.pubsubmiddleware.PubSubMiddleware.<init>(PubSubMiddleware.java:58)
01-04 23:03:26.786: E/AndroidRuntime(21793):    at      iotsuite.pubsubmiddleware.IoTSuiteFactory.getInstance(IoTSuiteFactory.java:16)
01-04 23:03:26.786: E/AndroidRuntime(21793):    at  sim.deviceD9.Startup.setUpNode(Startup.java:25)
01-04 23:03:26.786: E/AndroidRuntime(21793):    at sim.deviceD9.Startup.startDevice(Startup.java:63)
01-04 23:03:26.786: E/AndroidRuntime(21793):    at com.example.android.MainActivity.onCreate(MainActivity.java:21)
01-04 23:03:26.786: E/AndroidRuntime(21793):    at android.app.Activity.performCreate(Activity.java:6259)
01-04 23:03:26.786: E/AndroidRuntime(21793):    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1130)
01-04 23:03:26.786: E/AndroidRuntime(21793):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2379)
01-04 23:03:26.786: E/AndroidRuntime(21793):    ... 9 more

Upvotes: 2

Views: 2295

Answers (1)

hardillb
hardillb

Reputation: 59608

The problem is your URI is using the http:// scheme. http:// is for connecting to HTTP servers not MQTT brokers.

You need to use the tcp:// URI for Android (this might work for NodeJS as well, but mqtt:// definately works for NodeJS

mqtt://192.168.0.105

var mqtt = require('mqtt');
var client = mqtt.connect('mqtt://192.168.0.105');
setInterval(function() {
var data = {
     "tempValue" : Math.random(),
     "unitOfMeasurement" : 'C'
     };
client.publish('tempMeasurement', JSON.stringify(data));
}, 5000);

Upvotes: 1

Related Questions