uni-app实现本地MQTT连接的方法步骤
最近接到安卓端的需求,要求使用MQTT连接实现设备信息的收发。
可能有兄弟不太清楚 MQTT协议 是什么,简单地说它是一种轻量级的、基于发布/订阅模式的消息传输协议,广泛用于物联网(IoT)领域。
常见的操作就是连接后有N个设备订阅了主题A,这时候任意一台设备对主题A发布了一条信息,则当前N个设备都能收到这条消息。
至于其他的也不用知道的太清楚,反正知道一般是这么玩的就行。
假如你想知道的更为详细,可以询问 Trae。

需求
- 实现MQTT连接
- 实现主题(Topic)订阅
- 能够发送消息
- 能够接收消息
实现方案
首先是安装 mqtt.js 插件和 uuid.js 插件。
npm i mqtt@3.0.0 uuid
注意: 这里一定要安装 mqtt v3.0 版本,我之前装了一个 v5.x 版本,有比较大的 API 改动。项目上时间紧张,遂没有再尝试。(有兴趣的朋友可以考虑用最新版实现)
uuid 只是起到生成 连接ID 和 消息ID 的作用,这里也可以直接使用时间戳的方式,但是为了保证不重复,这里便不再更换了。
// mqttClient.js 对 MQTT 的简单封装
let client = null;
/**
* 初始化 MQTT 连接
* @param {Object} options
* @param {string} options.host - 服务器地址(不带协议)
* @param {number} options.port - 端口(通常 WebSocket 是 8083、8084 或 443)
* @param {string} options.clientId - 客户端 ID(建议唯一)
* @param {string} [options.username] - 用户名
* @param {string} [options.password] - 密码
* @param {boolean} [options.useWss=false] - 是否使用 wss(HTTPS)
*/
export function initMqtt(options) {
const {
host,
port,
clientId,
username = '',
password = '',
useWss = false
} = options;
// 根据平台选择协议(App 和 H5 用 ws/wss,小程序用 wxs/wss)
let protocol = 'ws';
if (useWss) protocol = 'wss';
// #ifdef MP-WEIXIN
protocol = useWss ? 'wxs' : 'wxs';
// #endif
const url = `${protocol}://${host}:${port}/mqtt`; // 注意:路径可能是 / 或 /mqtt,根据你的 broker 配置
const connectOptions = {
clientId: clientId,
username: username,
password: password,
keepalive: 60, // 心跳间隔(秒)
reconnectPeriod: 5000, // 自动重连间隔(毫秒)
connectTimeout: 10000, // 连接超时
clean: true // 是否清除会话
};
// 引入 mqtt(必须用 min 版本,否则小程序报错)
const mqtt = require('mqtt/dist/mqtt.min.js');
client = mqtt.connect(url, connectOptions);
// 监听连接事件
client.on('connect', () => {
console.log('MQTT 连接成功');
});
client.on('reconnect', () => {
console.log('MQTT 正在重连...');
});
client.on('error', (err) => {
console.error('MQTT 连接错误:', err);
});
client.on('close', () => {
console.log('MQTT 连接已关闭');
});
return client;
}
/**
* 订阅主题
* @param {string} topic
* @param {Function} callback - (topic, message) => {}
*/
export function subscribe(topic, callback) {
if (!client) {
console.warn('MQTT 客户端未初始化');
return;
}
client.subscribe(topic, (err) => {
if (!err) {
console.log(`订阅主题成功: ${topic}`);
} else {
console.error('订阅失败:', err);
}
});
// 监听消息(全局监听,需配合 topic 过滤)
client.on('message', (receivedTopic, message) => {
// if (receivedTopic === topic) {
try {
// 尝试解析 JSON
const payload = JSON.parse(message.toString());
callback(receivedTopic, payload);
} catch (e) {
// 非 JSON 消息
callback(receivedTopic, message.toString());
}
// }
});
}
/**
* 发布消息
* @param {string} topic
* @param {string|object} message
*/
export function publish(topic, message) {
if (!client) {
console.warn('MQTT 客户端未初始化');
return;
}
const payload = typeof message === 'object' ? JSON.stringify(message) : message;
client.publish(topic, payload, {
qos: 1
}, (err) => {
if (err) {
console.error('发布失败:', err);
} else {
console.log(`发布成功: ${topic}`, payload);
}
});
}
/**
* 断开连接
*/
export function disconnect() {
if (client) {
client.end(true); // true 表示强制断开
client = null;
console.log('MQTT 已断开');
}
}
我让 Trae 基于网上的封装简单进行了修改,生成了上述封装Js文件。
注意:在监听消息的部分,如果你的 Topic 是固定的,则请将 if (receivedTopic === topic) 的注释打开,如果不是,则注释掉,后续有详解。
现在进入到 page/index/index.vue 文件中
import {initMqtt, subscribe, publish, disconnect} from './mqttClient.js';
export default {
data() {
return {
host: 'broker.emqx.io',
messages: []
}
},
mounted() {
this.connect()
},
beforeDestroy() {
this.disconnect()
},
methods: {
// 连接
connect() {
const uuid = uuidv4();
const client = initMqtt({
host: this.host,
port: 8083,
clientId: uuid,
username: '',
password: '',
useWss: false // 如果是 HTTPS/WSS,设为 true
});
if (client) {
this.subscribeTopic();
}
},
// 订阅 test/topic 主题
subscribeTopic() {
subscribe('test/topic', (topic, message) => {
// 接收到的消息
const msg = JSON.stringify(message);
this.messages.unshift(msg);
});
},
// 订阅 带通配符 的主题
subscribeTopics() {
subscribe('+/topic', (topic, message) => {
// 接收到的消息
const msg = JSON.stringify(message);
this.messages.unshift(msg);
});
},
// 发送消息到 test/topic 主题
publishMessage() {
publish('test/topic', {
name: 'uni-app',
time: new Date().toISOString(),
msg: '测试信息'
});
},
disconnect() {
disconnect();
}
}
}
注意:在卸载页面的时候建议将 MQTT连接 断开,或者在 uni-app 中使用也可以使用 unload 方法断开连接。
另外订阅主题可以采用常规的,确定性的 Topic 主题名称,也可以采用 通配符(+) 的主题名称。
Trae还提醒我一定要注意,假如你的 Topic 为:
123/456/report 则你的通配符主题名称为 +/+/report
假如你的 Topic 为:
/123/456/report 则你的通配符主题名称为 +/+/+/report,因为他的第一位是 空字符串。
结论
在开发 IoT 设备时这个协议用的比较广泛,如果不接触这个方面一般不会用上这个。
另外 MQTT 本身自带心跳和自动重连机制,大致上相当于 WebSocket,这个部分一般不需要做特殊开发。
到此这篇关于uni-app实现本地MQTT连接的文章就介绍到这了,更多相关uni-app本地MQTT连接内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
javascript基于HTML5 canvas制作画箭头组件
该组件实现了根据箭头起止点坐标画箭头功能。目前组件可设置箭头形状(大小和角度)。2014-06-06
深入理解webpack process.env.NODE_ENV配置
这篇文章主要介绍了深入理解webpack process.env.NODE_ENV配置,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧2020-02-02
JS判断输入字符串长度实例代码(汉字算两个字符,字母数字算一个)
下面小编就为大家带来一篇JS判断输入字符串长度实例代码(汉字算两个字符,字母数字算一个)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧2016-08-08
原生JS版和jquery版实现checkbox的全选/全不选/点选/行内点选(Mr.Think)
脚本之家小编之前整理不少checkbox全选全不选这方便的文章,但看了这篇以后发现实现方法更好2016-10-10


最新评论