WebSocket connection failed SOLUTION

Hi, my name is Ema and i’m making this guide because the documentation and the examples in the main page are a little outdated with the mqtt.js library.

If you are using the mqtt.js library with your web app and cannot for the love of god connect to your HiveMQ cluester and keep receiving this error on console:
WebSocket connection to ‘ws://yourbrokerurl:8884/’ failed (or similar)

You’re probably using an incomplete string for the host.
It needs to have a specific prefix (wss://) and sufix (/mqtt):
‘wss://yourHiveMQbrokerurl:8884/mqtt’

Example code using react to show temperature and humidity from a ESP8266 board with HiveMQ as the broker:

App.js

import React, { useState, useEffect } from 'react';
import mqtt from 'mqtt/dist/mqtt'; //using only 'mqtt' throws some error about polyfills.


const mqttHost = 'wss://YOURBROKERURL:8884/mqtt';
const tempTopic = 'YOURTEMPTOPIC';
const humTopic = 'YOURHUMTOPIC';
const username = 'YOURUSERNAME';
const password = 'YOURPASS';


const options = {
  username,
  password,
  clientId: `mqttjs_${Math.random().toString(16).substr(2, 8)}`, //can be changed for something more specific if you need it
};

const App = () => {
  const [temp, setTemp] = useState(0);
  const [hum, setHum] = useState(0);

  useEffect(() => {
    const client = mqtt.connect(mqttHost, options);

    client.on('connect', () => {
      console.log('Connected to HiveMQ Cloud');
      client.subscribe(tempTopic);
      client.subscribe(humTopic);
    });

    client.on('message', (topic, message) => {
      if (topic === tempTopic) {
        setTemp(parseFloat(message.toString()));
      } else if (topic === humTopic) {
        setHum(parseFloat(message.toString()));
      }
    });

    return () => {
      client.end();
    };
  }, []);

  return (
    <div>
      <h1>Temperature: {temp} &deg;C</h1>
      <h1>Humidity: {hum} %</h1>
    </div>
  );
};

export default App;

Index.js:

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import './index.css';

ReactDOM.render(<App />, document.getElementById('root'));

Some additional info you may need if you are new (this does appear in the documentation):

  • Your browser cant use raw mqtt data, it needs to “encapsule” the data in WebSockets for it to be safe for the browser (thats why you probably can connect to your HiveMQ broker through mqtt using the port 8883 in apps like MQTT explorer)
  • You need to use WSS (web socket secure)
  • You need to use the port 8884 (default)
  • You dont need SSL certificates for this connection, but hiveMQ does support it if you want it.

Sorry for the bad english, it is not my first lenguage.
I’m posting this because i have seen A LOT of posts with this problem, but no solutions.
That and the fact that i spent probably 20 hours trying to make this work.

Be free to correct anything that is technically wrong in the post, im sure there is a lot because im a newbie too.
Good luck with your projects, everyone!

3 Likes

Great post thank you. I am using the Angular 13 wrapper for MQTT.js - ngx-mqtt | More than just a wrapper around MQTT.js for angular

Hi Ema, thanks for posting this. I found a lot of topics with the same problem too, but still following this guide I am having the connection problem to the url.

  useEffect(() => {
      const url = 'wss://b372c355b85c47dfa2d0e2633ec16662.s1.eu.hivemq.cloud:8884/mqtt'
      const options = {
        clientId: `mqttjs_${Math.random().toString(16).substring(2, 8)}`,
        username: 'my-user',
        password: 'my-pass'
      }

      const client = mqtt.connect(
        url,
        options
      )

      client.on('connect', () => {
        console.log('Connected to MQTT broker')
        client.subscribe('your-topic')
      })

      client.on('message', (topic, payload) => {
        setMqttMessage(payload.toString())
      })

      client.on('error', (error) => {
        try {
          console.error('MQTT Error:', error)
        } catch (err) {
          console.error('Error in error handler:', err)
        }
      })

      setMqttClient(client)

    return () => {
      if (mqttClient) {
        mqttClient.end()
      }
    }
  }, [])

Also checked if the port is available using the command on mac:
nc -zv b372c355b85c47dfa2d0e2633ec16662.s1.eu.hivemq.cloud 8884

what gives me:
Connection to b372c355b85c47dfa2d0e2633ec16662.s1.eu.hivemq.cloud port 8884 [tcp/*] succeeded!

Can you help me to understand what I am missing?