Search code examples
react-nativemqttemqx

MQTT client connects to Cloud but RN app does not


I have an EMQX cloud environment where the MQTTX client is connecting to, this works and i can publish and receive messages.

MQTTX Configuration

enter image description here

But when trying to connect to the same service in React-Native, it does not work and i keep receiving Socket Closed, undefined or Timeout errors.

My Code

import init from "react_native_mqtt";
import AsyncStorage from "@react-native-async-storage/async-storage";

init({
  size: 10000,
  storageBackend: AsyncStorage,
  defaultExpires: 1000 * 3600 * 24,
  enableCache: true,
  reconnect: true,
  sync: {},
});

const options = {
  host: "a1b2c3d4.oxo.oco-southeast1.emqxsl.com",
  port: 8883,
  path: "/mqtt",
  id: "id_" + parseInt(id.toString()),
};
const client = new Paho.MQTT.Client(options.host, options.port, options.path, options.id);

export const App: FC<HomeStackScreenProps<"Home">> = ({ navigation, route }) => {

  const connect = async () => {
    if (client.isConnected()) {
      if (__DEV__) console.log("🚫 - Previous client connected? ", client.isConnected());
      if (__DEV__) console.log("🚫 - Closing previous client? ", client.disconnect());
      onConnect();
    } else {
      client.connect({
        timeout: 3,
        userName: "test",
        password: "**********",
        keepAliveInterval: 60,
        cleanSession: true,
        useSSL: true,
        onSuccess: onConnect,
        onFailure: onFailure,
        reconnect: true,
        mqttVersion: 4,
      });
      console.log(client);
      setStatus("isFetching");
    }
  };
}

Solution

  • The solution for this problem is basically using a whole other library which supports mqtts protocols. I used react_native_mqtt which was fine at first but did not work with an online service like emqx cloud. so I changed my whole process to the library sp-react-native-mqtt. With some small, only every file that uses MQTT, code changes it worked perfectly!

    My code

    import MQTT from "sp-react-native-mqtt";
    
    const new_client = MQTT.createClient({
      clientId: options.clientId,
      uri: "mqtts://a1b2c3d4.oxo.oco-southeast1.emqxsl.com:8883",
      host: "a1b2c3d4.oxo.oco-southeast1.emqxsl.com",
      port: 8883,
      protocol: "mqtts",
      tls: true,
      keepalive: 60,
      clean: true,
      auth: true,
      user: "xoxo",
      pass: "xoxo1234",
    });
    
    export const App: FC<HomeStackScreenProps<"Home">> = ({ navigation, route }) => {
      useEffect(() => {
        new_client
          .then((client) => {
            client.on("closed", () => {
              console.log("mqtt.event.closed");
            });
    
            client.on("error", (msg) => {
              console.log("mqtt.event.error", msg);
              onFailure(msg);
            });
    
            client.on("message", (msg) => {
              console.log(msg)
            });
    
            client.on("connect", () => {
              onConnect();
              // You can access new_client.publish here
              client.publish("test", "test", 0, false);
            });
    
            return client; // return the client for further chaining
          })
          .catch((err) => {
            console.log(err);
          });
      }, []);
    return (
       // Some components
    )
    }
    

    Eventually after many debugging on Android it worked on both platforms and was connected to the EMQX Cloud. The comment of hardillb was part of the solution. With this library, the protocol is mqtts which is needed to connect to EMQX Cloud. One can also use websockets but I had to use mqtts.