next.jswebsocketmqttemqx

WSS MQTT Connection closes as soon as it connects to the broker in NextJS


I am using the context API to pass the same mqtt connection to child components. The problem is that as soon as the client connects to the broker (CONNACK), it immediately closes and starts reconnecting forever.

"use client";
import * as mqtt from "mqtt";
import React, {createContext, useEffect, useState} from "react";

interface MQTTContextType {
    client: mqtt.MqttClient | null,
    clientID: string,

}

export const MQTTContext = createContext({} as MQTTContextType);

const MQTT_URL = `wss://${process.env.NEXT_PUBLIC_EMQX_HOST}:${process.env.NEXT_PUBLIC_EMQX_PORT}/mqtt`;

export default function MQTTProvider ({   clientID,
                                          children,}: { clientID: string, children: React.ReactNode }){
    const [client, setClient] = useState<mqtt.MqttClient | null>(null);

    const MQTTOptions = {
        clientId: clientID,
        username: process.env.NEXT_PUBLIC_EMQX_USERNAME,
        password: process.env.NEXT_PUBLIC_EMQX_PASSWORD,
        keepAlive: 30,
    }

    useEffect(() => {
        
        if (client) {
            client.on("connect", () => {
                console.log("connected");
                //subscribe to test-mqtt topic
                client?.subscribe("test-mqtt", (err) => {
                    if(err){
                        console.log("error subscribing to test-mqtt topic", err);
                    }
                });
            });

            client.on("error", (err) => {
                console.log("error", err);
            });

            client.on("reconnect", () => {

                console.log("reconnecting");
            });

            client.on("close", () => {
                console.log("closed");
            });

            client.on("disconnect", () => {
                console.log("disconnected");
            });

            //on end
            client.on("end", () => {
                console.log("ended");

            });

            //listen to test topic
            client.on("message", (topic, message) => {
                console.log("message received", topic, message.toString());
            });

            //listeen to packet
            client.on("packetsend", (packet) => {
                console.log("packet sent", packet);
            });

            //listen to packetreceive
            client.on("packetreceive", (packet) => {
                console.log("packet received", packet);
            });

            //no we manually ping the broker
            const pingInterval = window.setInterval(() => {
                console.log("pinging")
                client.publish("ping", "ping "+ Date.now(), (err) => {
                    if(err){
                        console.log("error publishing ping", err);
                    }
                });
            }, 1000*30); //every 30 seconds

            return () => {
                client?.end();
                window.clearInterval(pingInterval);
            }
        } else {
            setClient(mqtt.connect(MQTT_URL, MQTTOptions));
        }
    }, [client, clientID]);

    const contextValue = {
        client,
        clientID
    };

    return (
        <MQTTContext.Provider value={contextValue}>
            {children}
        </MQTTContext.Provider>
    );

}

This is the output from the client

Browser console output

I am using EMQX Serverless so I cannot use logs.

I checked the port, the host url and also tried connecting to the broker using MQTTX client, but the problem only occurs in my webapp.


Solution

  • The problem was that WSS needed a secure connection which was not available in my localhost. Once I added a CA cert to localhost in firefox, it started working properly.