React+Next应用连接HiveMQ MQTT失败,寻求ESP32 JS通信方案
我基于React+Next开发应用,需要连接并控制ESP32,选择了HiveMQ的MQTT方案,但浏览器控制台持续循环报错:
WebSocket connection to 'ws://79642a966da549118f1128bb058d42ce.s2.eu.hivemq.cloud:8883/' failed:
已严格遵循HiveMQ官方文档操作,但问题仍未解决。希望有人帮忙排查该问题,或推荐更合适的JS与ESP32通信方案。我的index.tsx代码如下:
export default function Home() { const options = { username: 'gio.nacimento', password: 'Gio133ebu', }; const mqtt = require('mqtt'); // connect to your cluster, insert your host name and port const client = mqtt.connect('tls://79642a966da549118f1128bb058d42ce.s2.eu.hivemq.cloud:8883', options); // prints a received message client.on('message', function(topic: any, message: any) { console.log(String.fromCharCode.apply(null, message)); // need to convert the byte array to string }); // reassurance that the connection worked client.on('connect', () => { console.log('Connected!'); }); // prints an error message client.on('error', (error: any) => { console.log('Error:', error); }); // subscribe and publish to the same topic client.subscribe('messages'); client.publish('messages', 'Hello, this message was received from the app!'); const test = (): void =>{ client.subscribe('messages'); client.publish('messages', 'Hello, this message was received from the app by clicking!'); } return ( <div className='flex justify-center items-center flex-col'> <h1>Controle de LED</h1> <button onClick={test}>Test server</button> </div> ) }
一、MQTT连接失败排查方案
1. 协议与端口不匹配
你使用的是tls://协议,但报错显示浏览器尝试连接ws://端口8883。HiveMQ Cloud的WebSocket over TLS专属端口是8884,8883是原生MQTT的TLS端口,浏览器环境仅支持WebSocket协议,因此连接地址需修改为:
wss://79642a966da549118f1128bb058d42ce.s2.eu.hivemq.cloud:8884
2. Next.js组件内客户端初始化逻辑错误
直接在组件顶层初始化MQTT客户端会导致组件每次渲染都重建连接,引发循环重连,这也是控制台循环报错的核心原因之一。需用useEffect钩子包裹初始化逻辑,确保仅执行一次:
import { useEffect, useRef } from 'react'; import mqtt from 'mqtt'; // 改用ES模块导入,避免require导致的类型问题 export default function Home() { const options = { username: 'gio.nacimento', password: 'Gio133ebu', }; const clientRef = useRef<mqtt.Client | null>(null); useEffect(() => { const client = mqtt.connect('wss://79642a966da549118f1128bb058d42ce.s2.eu.hivemq.cloud:8884', options); clientRef.current = client; client.on('message', (topic, message) => { console.log(message.toString()); // 直接用toString转换字节数组更简洁 }); client.on('connect', () => { console.log('Connected!'); client.subscribe('messages'); client.publish('messages', 'Hello, this message was received from the app!'); }); client.on('error', (error) => { console.log('Error:', error); }); // 组件卸载时断开连接,避免内存泄漏 return () => { client.end(); }; }, []); // 空依赖数组确保初始化仅执行一次 const test = () => { clientRef.current?.publish('messages', 'Hello, this message was received from the app by clicking!'); // 无需重复订阅,连接成功时已完成订阅 } return ( <div className='flex justify-center items-center flex-col'> <h1>Controle de LED</h1> <button onClick={test}>Test server</button> </div> ) }
3. 认证与权限检查
- 确认HiveMQ Cloud控制台已添加该用户名和密码,且权限设置允许发布/订阅
messages主题; - 若开启了IP白名单,检查当前设备IP是否在允许列表内。
二、替代通信方案
如果MQTT方案仍存在问题,可考虑以下两种更直接的方案:
1. ESP32作为WebSocket服务器
在ESP32上通过ArduinoWebsockets库搭建WebSocket服务器,React应用直接通过ws://<ESP32局域网IP>:端口连接,无需中间MQTT broker。
- 优势:延迟低、架构简单,适合局域网内设备控制;
- 劣势:无法直接跨公网访问(需额外配置端口映射或内网穿透)。
2. HTTP API+ESP32 WebServer
在ESP32上搭建HTTP服务器,React应用通过fetch或axios发送GET/POST请求控制设备(例如http://<ESP32IP>/led?state=on)。
- 优势:前端实现简单,无需额外MQTT客户端依赖;
- 劣势:无法实时接收设备推送的消息(需结合轮询或WebSocket补充)。
内容的提问来源于stack exchange,提问作者Giovanna Nascimento

