TTN MQTT Broker Connection

Hello,
I am having a problem connecting my MQTT Client to the TTN Broker.
I’m using the Eclipse Paho MQTT Client in Java. With this Client I can connect to multiple different MQTT brokers but not to the TTN Broker.

I have seen, that the TTN Server does not support WebSockets, but i am connecting to the Server with tcp://eu.thethings.network:1883 so in my understanding i should not be using WebSockets.

Does anybody have any experience connecting to the TTN MQTT broker from a Paho Java MQTT client?

Is there anything I have to take into account when using the TTN MQTT broker?

If there are more informations I can provide just let me know.

Thanks

Edit: I’m using the Java Paho Client not C++

Typically with a debugging question you should include meaningful error messages. You may need to add some sensible exception handling logic to your code to do so.

You should probably experiment with mosquitto_sub before paho

Try really boring http - works for me in the various GUI clients - hopefully you tested in a vanilla GUI client first …

This doesn’t make any sense, the question was about MQTT, something that does not utilize http

http not tcp, that’s the protocol handler that works in the clients I use, but I am going off memory.

No. MQTT is a protocol on top of TCP (hopefully by way of SSL); it is not a protocol on top of HTTP on top of TCP.

Websockets would be a protocol on top of HTTP on top of TCP, but Websockets are not MQTT but rather an alternative type of non-MQTT connection which some MQTT broker packages also support.

OK, just remoted in to my developer machine in the office. All the connections start mqtt://

So I give myself half points for getting two of the letters correct plus a bonus point for suggesting the use of a GUI client for the simplest sanity check when code doesn’t work.

Except that the sanity check MQTT clients are CLI, not gui.

And while the tools in question might(?) tolerate a URL style prefix, they don’t need one: because MQTT is what they exist to speak, they just need to be told what host (and optionally, port) to connect to.

You are right I should have included this.
When connecting I get the error Message 5 connection Refused, not authorized.

When connecting to a local mosquitto broker on my machine with authentication I have no such problem.

This I already tried successfully. With mosquitto_sub I can connect to the TTN MQTT Broker.

Show the mosquitto_sub command line you use with any secrets x’d out, and show the code that is trying to use paho

eg, if you are passing account details to mosquitto_sub, you’ll also need to do so to paho probably with the .username_pw_set() method or whatever it looks like in Java (sorry, only tried in recently in python)

And you really should be using ssl, otherwise those account details go over the wire in cleartext…

mosquitto_sub -h eu.thethings.network -t '+/devices/+/up' -u appid -P ttn-account-v2.Ixxxxxxxxxg

This is the mosquitto_sub command with that i can connect to the TTN Broker.

private void config() {
	System.out.println(config.getBroker());
	String protocol;
	if(config.isEncryption()) {
		protocol = config.getSsl(); // protocol is either ssl://
	}else {
		protocol = config.getTcp(); // or tcp://
	}
	
	this.brokerUrl = protocol + config.getBroker() + colon + config.getPort();
	System.out.println(brokerUrl + " " + config.getUserName() + " " + config.getPassword());
	this.persistence = new MemoryPersistence();
	this.connectOptions = new MqttConnectOptions();
	
	try {
		this.mqttClient = new MqttClient(brokerUrl, config.getClient(), persistence);
		this.connectOptions.setCleanSession(false);
		if(config.isAuthentication()) {
			System.out.println("AUthentication"); //This block is executed so the credentials are set
			this.connectOptions.setPassword(config.getPassword().toCharArray());
			this.connectOptions.setUserName(config.getUserName());
		}
		this.mqttClient.connect(this.connectOptions);
		this.mqttClient.setCallback(this);
		this.init = true;
	}catch (MqttException me) {
		me.printStackTrace();//TODO: add logging?
	}
}

In this block the client is configured. Afterwards the subscribe is executed.
The configuration options come from a spring boot configuration file. The parameters are loaded and are present here.

public void subscribeMessage(String topic) {
	if(!init) {
		this.config();
	}
	try {
		this.mqttClient.subscribe(topic);
	} catch (MqttException me) {
		me.printStackTrace();// TODO: add logging?
	}
}

This is the code to subsribe to a topic. The error happens in the line: this.mqttClient.subscribe.

It is a paho exception: Not authorized to connect (5)

I have configured a local mosquitto broker with authentication and enforced it. To this broker i can connect with the paho client when the configuration is changed.

Of course i want to use SSL, but i thought i would go back to not using ssl until i can get a connection at all.

Hi @Crym4n, this is Paho MQTT client using python3 to TTN but the following simple REPL dialogue works:

$ python3
Python 3.7.3 (default, Jul 25 2020, 13:03:44)
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>
>>> import paho.mqtt.client as mqtt
>>>
>>> MQTT_SRVR = "eu.thethings.network"
>>> MQTT_USER = "<my-app-name>"
>>> MQTT_PASS = "ttn-account-v2.<my-app-key>"
>>>
>>> mqtt_client = mqtt.Client()
>>> mqtt_client.username_pw_set(MQTT_USER, MQTT_PASS)
>>> mqtt_client.connect(MQTT_SRVR)
0
>>>

This seems to work for me too.
My guess so far is, that either the Java Paho client does something strange, or i missed something in my implementation

Sadly I’m bound to the Java Spring Boot Project, so I can’t really switch to Python

What exactly is the order of things happening in your code?

Are you getting a connected callback?

Where are you trying to subscribe? Normally you would do this from the connected callback; at the very least you cannot attempt to subscribe until you have a connected callback

My suspicion here is that you aren’t using the connected callback, but trying to subscribe after you’ve started the connection attempt but before you are actually connected. (it’s possible in the local test case things are fast and you win the race condition even though that’s an invalid approach)

While I don’t think it’s your issue, also be vary aware of issues with various string encodings in passing username, password, topics etc.

You can see, that the config method is called before the subscribe. Once the configuration has run it is not run again.

What do you mean with that? I’m not getting any output on the console about being connected.

Do you have any idea how i could check for that? I’m not sure how to check for that. Maybe I could setup another broker online?

I have checked the string encodings by passing them to the command line, and also tried some encodings so I’m reasonably sure that that is not the problem.

I think you probably need to spend some time studying a generic paho-in-Java example, as you are not really understanding how it needs to be used.

An MQTT client has an event loop method that needs to be polled; you can either have your own thread or main loop that does this, or typically the client library language bindings can do it for you.

Most operations such as subscription are simply invalid when there is no active connection. As such, you would typically subscribe not after requesting connection, but rather from the connection callback method’s success case. Otherwise, you’re going to have to spin in a loop until you discover that status is connected.

And that loop, or some loop needs to be pumping the MQTT loop method.

Again, start with a generic example for a Java MQTT client.

Okay, I based my client on this Article.

Maybe there is something wrong with that that you can see.

But I will also search for other example clients and maybe test another one.

Thanks for your help!

The author of that doesn’t seem to know what they are doing. Likely they similarly lucked out in their test case (as you seem to have in your local server test) in having a situation where the connection succeeded before they tried to blindly subscribe without waiting for it. Further evidence of not understanding the task is the lack of doing anything in the disconnect callback and not just not making subscribing contingent on the connect one.

I will disregard this example then and look for new ones.

Thank you very much for your help and assessment.

If I find a better working example and get it to work I will report back. Maybe that can help anyone in the future.

I’ve spend some more time looking at this and tried something else.
I have now implemented the paho client with the help of spring integration.

Now testing out the new client I’ve encountered the same problem:
I can connect to a local server with authentication, but when trying to connect to the TTN Broker i again encounter the Not authorized to connect error message.
Again I can still connect to the TTN Broker using mosquitto_sub.

Are there any other limitations with the TTN Broker that prohibit me to connect?
I can not figure out what is happening.
I will include the new Java code:

public class MQTTClient {

@Autowired
private MQTTConfig config;

@Bean
public MqttPahoClientFactory mqttClientFactory() {
	DefaultMqttPahoClientFactory factory = new DefaultMqttPahoClientFactory();
	MqttConnectOptions options = new MqttConnectOptions();
	
	options.setServerURIs(new String[] { config.getUri()});
	options.setUserName(config.getUsername());
	options.setPassword(config.getPassword().toCharArray());
	options.setCleanSession(true);
	
	factory.setConnectionOptions(options);
	
	System.out.println(config.getUri() + config.getUsername() + config.getPassword());
	return factory;
}

@Bean
public MessageChannel mqttInputChannel() {
	return new DirectChannel();
}

@Bean
public MessageProducer inbound() {
	MqttPahoMessageDrivenChannelAdapter adapter = new MqttPahoMessageDrivenChannelAdapter(config.getClientID(), mqttClientFactory(), config.getTopic());
	adapter.setCompletionTimeout(50000);
	adapter.setConverter(new DefaultPahoMessageConverter());
	adapter.setQos(config.getQos());
	adapter.setOutputChannel(mqttInputChannel());
	return adapter;
}

@Bean
@ServiceActivator(inputChannel = "mqttInputChannel")
public MessageHandler handler() {
	return new MessageHandler() {

		@Override
		public void handleMessage(Message<?> message) throws MessagingException {
			System.out.println(Thread.currentThread().getName() + ":" + Thread.currentThread().getId() + ":" + message.getPayload());
		}
		
	};
}

}

Does anybody have some experience using the Paho Java Client to connect to the TTN Broker?