11

I'm working on a device that sense and collect information from the environment such as temperature, humidity, etc.

The device is not connected to any power source, but it has a battery, and a solar panel to charge it.

It's almost in a deep sleep state most of the time, and it only wake up when it need to sense and transfer data. This operation takes about 1-2 minutes, and then it goes to sleep again.

I'm not an expert in this area, but I think MQTT should be a good option if the device need to be accessible to receive messages from a topic all the time, but in my scenario it only read sensors, and send data to a server periodically.

Currently I'm sending the data through HTTP, but I'm wondering if it makes sense to implement MQTT? Should I get any advantage over HTTP for this scenario?

zephrax
  • 127
  • 1
  • 1
  • 6
  • 1
    You might find [this question](https://iot.stackexchange.com/questions/44/when-and-why-to-use-mqtt-protocol) on the IoT site interesting to read. You could also ask there if you don't get any answers on Stack Overflow—the IoT site might be more focused on the bits you're interested in. – Aurora0001 May 19 '17 at 16:50

4 Answers4

27

There is a rich literature around MQTT vs. HTTP which you should delve into for details, but here are some of the high points for your application.

MQTT

  • MQTT allows for persistent connections which can save significant resources over HTTP. This is most relevant if you are using SSL.
  • If you are only sending a few metrics MQTT will generally be more bandwidth efficient than HTTP.
  • As MQTT is designed for delivering data (not entire pages) its pub / sub model offers many useful built-in features such as retention and last will.
  • Also MQTT offers a simple way of implementing encryption, authentication, and access control.
  • MQTT is intended for situations where your connection may be intermittent or otherwise unreliable. Its various Quality-of-Service levels provide you with significant ways of ensuring that data is sent reliably.
  • In larger applications the MQTT broker provides for easier management in my experience. I particularly like that there is a standardized set of metrics for measuring performance.
  • The topic/subtopic value structure of MQTT helps to organize your data and makes it easy to scale things up and share resources between multiple projects.
  • This may be personal preference, but I find the MQTT protocol easier to understand, troubleshoot, and program than working with HTTP. In particular, the Python Paho MQTT library is simple and works well.

In summary, MQTT has many features which would seem to be perfect for your application. That said, you could likely replicate many of them using HTTP but it would require more work.

HTTP

  • Pretty much supported everywhere which ensures easier compatibility with firewalls. This could be important if you are deploying on networks you do not control.

  • It is a more common protocol so you (and your end users) may already feel comfortable with it. Similarly you may already understand the security model which would make it easier to secure.

  • There are some differences between different MQTT implementations which might cause difficulties (i.e I use Mosquitto and sometimes find it confusing when people talk about their HiveMQ setup). HTTP strikes me as more universal and has a much larger community of people available to help you.

So HTTP has some inherent disadvantages versus MQTT but it will get the job done and may be more practical if the specific features of MQTT don't appeal to you.

But really if this is a large-scale project it is worth trying both and running some benchmarks and tests in your particular application and environment. It wouldn't be hard to set up a test environment and get some metrics. If this is more of a hobby / one-off project then I would use whichever one you are more comfortable with or find more interesting.

Sources / Further Reading:

http://stephendnicholas.com/posts/power-profiling-mqtt-vs-https https://www.ibm.com/developerworks/community/blogs/sowhatfordevs/entry/using_mqtt_protocol_advantages_over_http_in_mobile_application_development5?lang=en https://medium.com/@shubhanshusingh/http-vs-mqtt-9008d448bf88 https://www.slideshare.net/paolopat/mqtt-iot-protocols-comparison https://mobilebit.wordpress.com/2013/05/03/rest-is-for-sleeping-mqtt-is-for-mobile/ http://bec-systems.com/site/1200/iot-protocols-mqtt-vs-coap-vs-http

blp
  • 578
  • 1
  • 5
  • 9
5

We have tested MQTT vs HTTP(REST) over SSL from normal server and Raspberry Pi boards both from performance point of view and from energy consumption. The results depend on use-case and device where process is running.

Regarding your use case we have special test as well => delivering many messages (multiple probes) via HTTP, HTTP-batch or MQTT. The results are quite simple, if you have possibility to send data in one HTTP request - it will be the best option. MQTT is on the second place and HTTP with per-message delivery is much less power efficient and slower then MQTT.

shal
  • 161
  • 1
  • 1
1

I am new to the game but I love mqtt for collecting data and sending info to devices.

I am using the synapses rf200 chips (self healing mesh network) and I have built a bridge by connecting one of the rf200's serially to an esp8266 wifi chip.

Basically I have mqtt_in and mqtt_out as topics and my c# xamarin iOs/android application connects to the mqtt broker requests information from the rf200's using mqtt_in (in to the rf200 mesh network) and the nodes respond using mqtt_out (out of the rf200 mesh network) I collect all the information as strings parse as necessary and convert it to whatever I need it to be.

It's very low overhead and the mqtt broker is very easy to set up.

Mark
  • 503
  • 6
  • 20
-2

I think MQTT is best for u..You can use eclipse paho library.. This class may help u.

public class PahoMqttClient {

private static final String TAG = "PahoMqttClient";
private MqttAndroidClient mqttAndroidClient;

private String broker_userName,broker_password; public MqttAndroidClient getMqttClient(Context context, String brokerUrl, String clientId,String broker_password) {

    this.broker_userName=clientId;
    this.broker_password=broker_password;

    mqttAndroidClient = new MqttAndroidClient(context, brokerUrl, clientId);
    try {
        IMqttToken token = mqttAndroidClient.connect(getMqttConnectionOption(), null, new IMqttActionListener() {
                    @Override
                    public void onSuccess(IMqttToken iMqttToken) {
                        Log.d(TAG, "Success");
                    }

                    @Override
                    public void onFailure(IMqttToken iMqttToken, Throwable exception) {
                        Log.d(TAG, "Failure " + exception.toString());

                    }
                });


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

    return mqttAndroidClient;
}

public void disconnect(@NonNull MqttAndroidClient client) throws MqttException {
    IMqttToken mqttToken = client.disconnect();
    mqttToken.setActionCallback(new IMqttActionListener() {
        @Override
        public void onSuccess(IMqttToken iMqttToken) {
            Log.d(TAG, "Successfully disconnected");
        }

        @Override
        public void onFailure(IMqttToken iMqttToken, Throwable throwable) {
            Log.d(TAG, "Failed to disconnected " + throwable.toString());
        }
    });
}

@NonNull
private DisconnectedBufferOptions getDisconnectedBufferOptions() {
    DisconnectedBufferOptions disconnectedBufferOptions = new DisconnectedBufferOptions();
    disconnectedBufferOptions.setBufferEnabled(true);
    disconnectedBufferOptions.setBufferSize(100);
    disconnectedBufferOptions.setPersistBuffer(false);
    disconnectedBufferOptions.setDeleteOldestMessages(false);
    return disconnectedBufferOptions;
}

@NonNull
private MqttConnectOptions getMqttConnectionOption() {
    MqttConnectOptions mqttConnectOptions = new MqttConnectOptions();
    mqttConnectOptions.setCleanSession(false);
    mqttConnectOptions.setAutomaticReconnect(true);
    mqttConnectOptions.setKeepAliveInterval(120);
    //mqttConnectOptions.setWill(Constants.PUBLISH_TOPIC, "I am going offline".getBytes(), 1, true);
    mqttConnectOptions.setUserName(broker_userName);
    mqttConnectOptions.setPassword(broker_password.toCharArray());
    return mqttConnectOptions;
}


public void publishMessage(@NonNull MqttAndroidClient client, @NonNull String msg, int qos, @NonNull String topic)
        throws MqttException, UnsupportedEncodingException {
    byte[] encodedPayload = new byte[0];
    encodedPayload = msg.getBytes("UTF-8");
    MqttMessage message = new MqttMessage(encodedPayload);
    message.setId(320);
    message.setRetained(false);
    message.setQos(qos);
    try {
        client.publish(topic, message);
    }catch (Exception e){ Log.e("PUB", e.getMessage());}

}

public void subscribe(@NonNull MqttAndroidClient client, @NonNull final String topic, int qos) throws MqttException {
    IMqttToken token = client.subscribe(topic, qos);
    token.setActionCallback(new IMqttActionListener() {
        @Override
        public void onSuccess(IMqttToken iMqttToken) {
            Log.d(TAG, "Subscribe Successfully " + topic);
        }

        @Override
        public void onFailure(IMqttToken iMqttToken, Throwable throwable) {
            Log.e(TAG, "Subscribe Failed " + topic);

        }
    });
}

public void unSubscribe(@NonNull MqttAndroidClient client, @NonNull final String topic) throws MqttException {

    IMqttToken token = client.unsubscribe(topic);

    token.setActionCallback(new IMqttActionListener() {
        @Override
        public void onSuccess(IMqttToken iMqttToken) {
            Log.d(TAG, "UnSubscribe Successfully " + topic);
        }

        @Override
        public void onFailure(IMqttToken iMqttToken, Throwable throwable) {
            Log.e(TAG, "UnSubscribe Failed " + topic);
        }
    });
}

}