Configuring C++ Application to publish messages to Cumulocity using Mosquitto

I am currently developing a C++ application with the Momentics IDE that is hosted on a QNX OS running on VMware Player virtual machine. The application uses the MQTT protocol provided by Mosquitto to publish messages to Cumulocity IoT’s Device Management portal.

I had previously managed to establish a connection with Cumulocity and publish messages using a pre-built application in C# called the mqttMultimeter. The application would automatically create a new device once I published the message to the s/us topic.

Now, I am trying to replicate the same success with a C++ application using one of the example applications found in Mosquitto’s official Github repository under the folder examples > temperature conversion. The application contains a derived class, temperature_conversion.cpp that inherits all of the methods of mosquittopp.cpp .

I have been following the official documentation from Mosquitto to create a new mosquitto client, authenticate the client vis-a-vis Cumulocity, and publish messages to the MQTT broker. The corresponding methods are:

  1. connect()
  2. user_pw_set()
  3. publish()

Both publish() and user_pw_set() return integers to indicate whether their respective method call worked or not. Consequently, I wrote a couple of if blocks to verify whether the client is successfully connecting with the broker.

The program compiles without errors; however, when I go to the Device Management portal under Devices > All devices, there is no record of a new device being registered.

The full source code is posted below:

#include <iostream>
#include "temperature_conversion.h"

int main() {
	// declare temp_conversion instance
	class mqtt_tempconv *tempconv;

	// declare constants for host username and password.
	const char host_val[] {"[domain].cumulocity.com"};
	const char username_val[] {"[username]"};
	const char password_val[] {"[password]"};

	// define constant for port number.
	const int port {1883};

	// assign constants to pointers
	const char* host {host_val};
	const char* username {username_val};
	const char* password {password_val};

	// declare and define variable arguments for publish()
	int payloadlen {8};
	int qos {1};
	bool retain {true};

	// declare variables pointer arguments
	int mid_val {4};
	int *mid {&mid_val};
	char topic_val[] {"s/us"};
	char *topic {topic_val};
	char payload_val[] {"301, 208"};
	char *payload {payload_val};

	// Initialize mosquitto library
	mosqpp::lib_init();

	// Instantiate new tempconv (i.e.mosquittopp) object.
	// NOTE: mqtt_tempconv automatically connects to MQTT broker
	tempconv = new mqtt_tempconv("tempconv", host, port);

//	tempconv->loop_forever();

	// Set up username and password for authentication.
	int auth_status;
	auth_status = tempconv->username_pw_set(username, password);
	if(auth_status == MOSQ_ERR_SUCCESS){
		std::cout << "Authentication successful. Proceeding towards publishing message." << std::endl;
		// Publish message to Cumulocity MQTT broker.
		int publish_status;
		publish_status = tempconv->publish(mid, topic, payloadlen, payload, qos, retain);
		if(publish_status == MOSQ_ERR_SUCCESS){
			std::cout << "Success! Message published to Cumulocity MQTT broker." << std::endl;
		}
		else {
			std::cout << "Error: unable to publish message to Cumulocity MQTT broker.";
		}
	}
	else {
		std::cout << "Error: unable to connect to broker" << std::endl;
	}

	std::cout << "Disconnecting MQTT client..." << std::endl;
	int disconnect_status;
	disconnect_status =	tempconv->disconnect();
	if(disconnect_status == MOSQ_ERR_SUCCESS){
		std::cout << "Success! Disconnected MQTT client." << std::endl;
	}

	// Clean up mosquitto library
	mosqpp::lib_cleanup();

	return 0;
}

At first, I thought that the application was successfully connecting to Cumulocity. However, if I comment out the loop_forever() method, which establishes an infinite blocking loop, I get the following error message published repeatedly on my IDE’s console:

Connected with code 5.
Connected with code 5.
Connected with code 5.
Connected with code 5.
...

After doing quick a Google search, I discovered that code 5 corresponds to an error related to my certificate. I know from the mqttMultimeter application, that I needed to provide to provide a ClientID and that, furthermore, my username included my tenant ID. However, I do not see any methods in the Mosquitto documentation where I would insert this information.

Could the lack of those two steps be the reason why I am unable to connect with Cumulocity’s MQTT broker?

Note: I could not post any links to my post; apologies for the inconveniance.

Hi @luclib, according to the Mosquitto documentation, when a new client is created and the client ID is NULL, it will generate a random ID. Can you try this: const char username_val[] {"[tenantID]/[username]"};? I tested with my MQTT client application, without tenant ID it will return an error with code 5.

This also looks wrong. When sending 301 at least a type of the alarm should follow and no blanks e.g. 301,c8y_TemperatureAlarm.
The 5 error is because you missed to authenticate yourself properly. For port 1883 no certificate is needed. For 8883 you need to make sure the server certificate is known & trusted by your client.

Hi Yishu,

I tried that format at first but with no success; I should have specified that I used [tenantID]/[username] for the username_val[] variable.

I looked over the MQTT example in Cumulocity’s documentation and tried to modify my host as follows:

const char host_val[] {"[tenantID]/cumulocity.com/mqtt"}

This time I added a std::cout method to print out the status of the authentication and publication steps, and I got a more descriptive message, MOSQ_ERR_NO_CONN.

Authentication successful. Proceeding towards publishing message.
4
Error: unable to publish message to Cumulocity MQTT broker.Disconnecting MQTT client...
4

@Stefan_Witschel I set payload_val[] to {210, -87} this time.

Hi Stefan, I reran the application using with the parameters from my reply to Yishu but, this time, I changed my port to 8883.

Unfortunately, the resulting error message was the same.

Authentication successful. Proceeding towards publishing message.
4
Error: unable to publish message to Cumulocity MQTT broker.Disconnecting MQTT client...
4

I don’t understand the code completely but normally you can publish just everything when properly connected. If any issue occurred you get a message on “s/e” topic from the platform. So it is kind of strange you get an error when publishing something, indicating that you might not be properly connected. The error reasons would be interesting. But still, don’t send any blank in the payload:

210, -87210,-87

Hi Stefan, where do I go to access the "s/e" topic on the Cumulocity platform?

You subscribe to that topic “s/e”.
I would suggest to “play” with the MQTT interface using MQTTx or any other MQTT tool.

Hi guys @Stefan_Witschel @Yishu_Zhong

I am still working on getting the application up and running and it occurred to me to ask if the problem that I am seeing might have something to do with TLS certification. For the C# client app, I noticed that when I tried to use any TLS certification, I would get an error related to an SSL stream.

MQTTnet.Exceptions.MqttCommunicationException:  Received an unexpected EOF or 0 bytes from the transport stream.
 ---> System.IO.IOException:  Received an unexpected EOF or 0 bytes from the transport stream.
   at System.Net.Security.SslStream.<FillHandshakeBufferAsync>g__InternalFillHandshakeBufferAsync|189_0[TIOAdapter](TIOAdapter adap, ValueTask`1 task, Int32 minSize)
   at System.Net.Security.SslStream.ReceiveBlobAsync[TIOAdapter](TIOAdapter adapter)
   at System.Net.Security.SslStream.ForceAuthenticationAsync[TIOAdapter](TIOAdapter adapter, Boolean receiveFirst, Byte[] reAuthenticationData, Boolean isApm)
   at MQTTnet.Implementations.MqttTcpChannel.ConnectAsync(CancellationToken cancellationToken)
   at MQTTnet.Implementations.MqttTcpChannel.ConnectAsync(CancellationToken cancellationToken)
   at MQTTnet.Adapter.MqttChannelAdapter.ConnectAsync(CancellationToken cancellationToken)
   --- End of inner exception stack trace ---
   at MQTTnet.Adapter.MqttChannelAdapter.WrapAndThrowException(Exception exception)
   at MQTTnet.Adapter.MqttChannelAdapter.ConnectAsync(CancellationToken cancellationToken)
   at MQTTnet.Client.MqttClient.ConnectAsync(MqttClientOptions options, CancellationToken cancellationToken)
   at MQTTnet.Client.MqttClient.ConnectAsync(MqttClientOptions options, CancellationToken cancellationToken)
   at MQTTnetApp.Services.Mqtt.MqttClientService.Connect(ConnectionItemViewModel item) in C:\Users\lucas.liberman\source\repos\mqttMultimeter\mqttMultimeter-main\Source\Services\Mqtt\MqttClientService.cs:line 107
   at MQTTnetApp.Pages.Connection.ConnectionPageViewModel.Connect(ConnectionItemViewModel item) in C:\Users\lucas.liberman\source\repos\mqttMultimeter\mqttMultimeter-main\Source\Pages\Connection\ConnectionPageViewModel.cs:line 82

Hi @luclib,

as you are using C# now, this C# MQTT client tutorial may can help you. In this tutorial, port 8883 is bound to ‘ssl://’ while port 1883 requires ‘tcp://’. This could be the reason for the error.
I would also suggest to ‘play’ with some MQTT tool first.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.