0

Hi i am very new to MQTT and I have made a 2 MQTT client jar files , one that publishers to a topic (it takes 3 args , "topic" , "message" , "host address of broker"), and another that subscribes to a topic (takes 2 args "topic","host address of broker"). the clients both work fine when sending normal plain text messages. however i am required to implement a simple gzip compression of the payload, on both the publisher and the subscriber client. The publisher successfully compresses the payload and sends it off however i am running into a problem when i try add decompression of the payload to the client , in as far as it its the decompression method and does not go any further. I a aware that some parts of the code are inefficient however i am just looking for a answer to the decompression problem.

Publisher client code:

    package com;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.Scanner;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;

public class PahoDemo implements MqttCallback {

MqttClient client;
static String clientMessage="";
static String topic="";
static String ipAddress="";
static Scanner scan = new Scanner(System.in);
static byte[] compressedMessage;

public PahoDemo() {
}

public static byte[] compress(String data) throws IOException {
    ByteArrayOutputStream bos = new ByteArrayOutputStream(data.length());
    GZIPOutputStream gzip = new GZIPOutputStream(bos);
    gzip.write(data.getBytes());
    gzip.close();
    byte[] compressed = bos.toByteArray();
    bos.close();
    return compressed;
}

public static String decompress(byte[] compressed) throws IOException {
    ByteArrayInputStream bis = new ByteArrayInputStream(compressed);
    GZIPInputStream gis = new GZIPInputStream(bis);
    BufferedReader br = new BufferedReader(new InputStreamReader(gis, "UTF-8"));
    StringBuilder sb = new StringBuilder();
    String line;
    while((line = br.readLine()) != null) {
        sb.append(line);
    }
    br.close();
    gis.close();
    bis.close();
    return sb.toString();
}


public static void main(String[] args) throws IOException {

    new PahoDemo().setDetails(args[0], args[1],args[2]);
    new PahoDemo().TestPahoClientPub();

}

public void setDetails(String topic,String message,String ipAddressEntered){
    PahoDemo.topic=topic;
    PahoDemo.clientMessage=message;
    PahoDemo.ipAddress="tcp://"+ipAddressEntered+":1883";
}

public void TestPahoClientPub() throws IOException{
    System.out.println("test pub ");
    try {
          MqttClient client = new MqttClient(ipAddress, "publisher");
          client.connect();
          MqttMessage message = new MqttMessage();
          compressedMessage = PahoDemo.compress(clientMessage);
          clientMessage = compressedMessage.toString();
          message.setPayload(clientMessage.getBytes(Charset.forName("UTF-8")));
          client.publish(topic, message);
          client.disconnect();
        } catch (MqttException e) {
          e.printStackTrace();
        }
      }


public void doDemo() {
    System.out.println("test sub");

    try {
        client = new MqttClient(ipAddress, "Subscriber");
        client.connect();
        client.setCallback(this);
        client.subscribe(topic);
    } catch (MqttException e) {
        e.printStackTrace();
    }
}

Subscriber client code:

package com;
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.eclipse.paho.client.mqttv3.MqttCallback;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

import org.apache.commons.compress.utils.IOUtils;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;


class SimpleCallback implements MqttCallback {

    public static byte[] compress(String data) throws IOException {
        ByteArrayOutputStream bos = new ByteArrayOutputStream(data.length());
        GZIPOutputStream gzip = new GZIPOutputStream(bos);
        gzip.write(data.getBytes());
        gzip.close();
        byte[] compressed = bos.toByteArray();
        bos.close();
        return compressed;
    }

    public static String decompress(final byte[] compressed) throws IOException {
        ByteArrayInputStream bis = new ByteArrayInputStream(compressed);
        GZIPInputStream gis = new GZIPInputStream(bis);
        byte[] bytes = IOUtils.toByteArray(gis);
        return new String(bytes, "UTF-8");
}

        public static String decompressArrived(MqttMessage message) throws IOException{
            byte[] messagePayload = message.getPayload();
            String messageDecompressed = decompress(messagePayload).toString();
            return messageDecompressed;
        }

        @Override
        public void connectionLost(Throwable cause) { //Called when the client lost the connection to the broker
        }

        @Override
        public void messageArrived(String topic, MqttMessage message) throws Exception {
            System.out.println("-------------------------------------------------");
            System.out.println("| Topic:" + topic);
            System.out.println("| Message: " + new String(SimpleCallback.decompressArrived(message))); // here is the problem where the code stops
            System.out.println("-------------------------------------------------");
        }

        @Override
        public void deliveryComplete(IMqttDeliveryToken token) {//Called when a outgoing publish is complete
        System.out.println("delivery complete");
        }
}




public class MqttPublishSubscribeSample {
    public static void main(String[] args){
        String topic = args[0];  // topic name
        String content = "Message from MqttPublishSample"; //payload of message
        int qos = 2; 
        String broker = "tcp://"+args[1]+":1883";
        String clientId = "JavaSample";
        MemoryPersistence persistence = new MemoryPersistence();

        try {
            MqttClient sampleClient = new MqttClient(broker, clientId, persistence);
            MqttConnectOptions connOpts = new MqttConnectOptions();
            connOpts.setCleanSession(true);
            System.out.println("Connecting to broker: " + broker);
            sampleClient.connect(connOpts);
            sampleClient.subscribe("#", 1);
            System.out.println("Connected");
            System.out.println("Publish message: " + content);
            MqttMessage message = new MqttMessage(content.getBytes());
            message.setQos(qos);
            sampleClient.setCallback(new SimpleCallback());
            sampleClient.publish(topic, message); // just  a test packet 
            System.out.println("Message published");
            try {
                Thread.sleep(5000);
            } catch(Exception e) {
                e.printStackTrace();
            }
        } catch(MqttException me){
            System.out.println("reason " + me.getReasonCode());
            System.out.println("msg " + me.getMessage());
            System.out.println("loc " + me.getLocalizedMessage());
            System.out.println("cause " + me.getCause());
            System.out.println("except " + me);
            me.printStackTrace();
        }
    }
}

basically is there any modifications i can make to the messageArrived method in the subscriber client to allow it to print out the decompressed file.

Thanks.

NC24
  • 1
  • 4
  • Have you tested giving the compressed data direct to the decompress function to check it actually can decompress the data correctly? BTW it is still possible the compressed data is wrong - if sent incorrectly that might produce the same symptom as the decompressor not being able to decompress – DisappointedByUnaccountableMod Dec 12 '16 at 18:17
  • put a try catch block round the call to `decompress()` as you are declaring that all the methods throw IOExceptions so they will just filter up until they are thrown away by the Paho library. – hardillb Dec 12 '16 at 18:30
  • thanks the try catch worked, getting a "not in gzip format" error now but atleast i can work with that. – NC24 Dec 12 '16 at 19:12
  • and yes i did test the compression and decompression, using separate test file with a simple main to test. and the compression and decompression worked fine. – NC24 Dec 12 '16 at 19:26
  • got it working fully now, the issue was the fact that i had not got my call to the decompress() method in a try catchblock, and also in my publisher client i was passing a string of the encoded gzip bytes instead of the actual gzip byte array. thanks for both of your help – NC24 Dec 12 '16 at 19:49

0 Answers0