javaandroidazureiotazure-iot-hub

Message to Azure IoT is several times larger than the actual message body


I am building an app in Java for Android. The app can communicate to an sensor device, receive recorded data from the device and send it to an Azure IoT hub. However, when I construct the message to send to Azure, the size of the message is over three times larger than the actural data recording I am trying to send. One recording from the device is around 370 kb, while the message constructed to be send to Azure ends up being around 1500 kb. I have followed this example for creating the part of the code sending data to Azure: send event example

Before sending the recorded data to Azure I construct a json object, because I also want to save the data locally as a backup, in case the Android cannot establish connection to Azure. I want the data (recording, time of recording, messageId, deviceId, etc.) I send to Azure to be identical to what is saved locally so I can match them later on if necessary.

Here is my code for constructing the JSON object I set at the body of the message to Azure:

public String createJson(ArrayList recSignal, String deviceId, String smartphoneId, int batterylevel) throws JSONException, UnsupportedEncodingException {

        JSONArray SysProp = new JSONArray();
        SysProp.put("SystemProperties");

        JSONObject SysPropValues = new JSONObject();
        try {
            SysPropValues.put("messageId", UUID.randomUUID().toString());
            SysPropValues.put("correlationId", "???");
            SysPropValues.put("connectionDeviceId", smartphoneId); //<-- name of smartphone device in the cloud
            SysPropValues.put("contentType", "UTF-8");
            SysPropValues.put("enqueuedTime", Instant.now().toString());
        } catch (
                JSONException e) {
            throw new JSONException(e);
        }
        SysProp.put(SysPropValues);

        JSONArray DeviceProp = new JSONArray();
        DeviceProp.put("DeviceProperties");

        JSONObject DevicePropValues = new JSONObject();
        try {
            DevicePropValues.put("deviceId", deviceId); //<-- MAC of the connected device
            DevicePropValues.put("deviceBatteryLevel", batterylevel);
        } catch (JSONException e) {
            throw new JSONException(e);
        }
        DeviceProp.put(DevicePropValues);

        JSONObject RecordingBody = new JSONObject();
        RecordingBody.put("Body", recSignal);

        JSONArray jsonmessage = new JSONArray();  //<-- json to be send to azure
        jsonmessage.put(SysProp);
        jsonmessage.put(DeviceProp);
        jsonmessage.put(RecordingBody);

        jsonmessagestring = jsonmessage.toString();

        Log.i("Service", "Size of JSON as string is: " + jsonmessagestring.getBytes("UTF-8").length/1000 + "kb");

        // *** HERE THE SIZE OF THE JSON OBJECT IS AROUND 370 KB ***

        return jsonmessagestring;

    }

Here is my code for sending to Azure. This is taken from the example mentioned earlier.

private boolean connectAndSend(String dataToSend, String connString, int numRepeatMessageSend) throws IOException, URISyntaxException, InterruptedException, IotHubClientException {

        DeviceClient client = new DeviceClient(connString, protocol);
        client.setMessageCallback(new MessageCallbackMqtt(), null);
        client.setConnectionStatusChangeCallback(new IotHubConnectionStatusChangeCallbackLogger(), new Object());
        Log.i("Service", "Successfully created an IoT Hub client with callback settings.");

        client.open(true);
        Log.i("Service", "Opened connection to IoT Hub.");


        // send message to azure
        Log.i("Service", "Constructing message to send to Azure");

        Message msg = new Message(dataToSend);
        msg.setContentType("application/json;charset=utf-8");
        boolean messageSend = false;

        Log.i("Service", "Size of message to send to azure is: " + Arrays.toString(msg.getBytes()).length()/1000 + "kb");
        
        // *** HERE THE SIZE OF THE MESSSAGE IS AROUND 1500 KB ***

        for (int i = 0; i < numRepeatMessageSend; i++) {
              try {
                   client.sendEvent(msg, D2C_MESSAGE_TIMEOUT_MILLISECONDS);
                   messageSend = true;
                   Log.i("Service", "Successfully send message to Azure");
                    
              } catch (IotHubClientException e) {
                   Log.i("Service", "Failed to send message to Azure. Status code: " + e.getStatusCode());
              }
        }

        // close the connection to client
        Log.i(TAG, "Closing client");
        client.close();
        return messageSend;
}

I read here about the message size of Azure IoT hub messages that the final size is the sum of the body size, values of the message system properties and user properties, so I understand the actual message send to Azure will be larger than the body of data I am trying to send, but I fail to understand why it ends up so much larger.

If anyone can explain me why or has a suggestion to reduce the message size it would be highly appreciated.


Solution

  • Before modification my message size. enter image description here

    public String createJson(ArrayList recSignal, String deviceId, String smartphoneId, int batterylevel) throws JSONException, UnsupportedEncodingException {
    
        JSONObject messageObject = new JSONObject();
    
        try {
            messageObject.put("messageId", UUID.randomUUID().toString());
            messageObject.put("correlationId", "???");
            messageObject.put("connectionDeviceId", smartphoneId);
            messageObject.put("contentType", "UTF-8");
            messageObject.put("enqueuedTime", Instant.now().toString());
            messageObject.put("deviceId", deviceId);
            messageObject.put("deviceBatteryLevel", batterylevel);
            messageObject.put("Body", recSignal);
        } catch (JSONException e) {
            throw new JSONException(e);
        }
    
        String jsonMessage = messageObject.toString();
    
        Log.i("Service", "Size of JSON as string is: " + jsonMessage.getBytes("UTF-8").length / 1000 + "kb");
    
        // *** NOW THE SIZE OF THE JSON OBJECT SHOULD BE SMALLER ***
    
        return jsonMessage;
    }
    

    enter image description here

    enter image description here

    enter image description here