核心功能有:
- 订阅、取消指定主题
- 发布指定主题
- 查看服务端所有主题
- 异常处理机制
- 重连机制
- 增加重连的最大次数
- 可以增加一个参数,用于设置重连的最大次数。如果重连次数超过了这个最大值,则直接停止重连,避免进入死循环。
- 增加重连的最大次数
- 心跳检测
- 客户端的连接状态、连接次数、连接时长和 Ping 值等信息管理。
- 给上层应用包暴露状态接口
后续想通过设计模式进行优化; 通过以上方法,上层应用可以及时地获取 MQTT 客户端的连接状态、连接次数、连接时长和 Ping 值等信息管理。
代码如下:
import mqtt from "mqtt";
class Mqtt {
// 构造器
constructor(mqttServer, mqttPort, mqttUser, mqttPassword) {
// 初始化数据
this.initData(mqttServer, mqttPort, mqttUser, mqttPassword);
// 绑定this指向
this._connect = this._connect.bind(this);
this._sendHeartbeat = this._sendHeartbeat.bind(this);
}
// 初始化数据
initData(mqttServer, mqttPort, mqttUser, mqttPassword) {
this.mqttServer = mqttServer;
this.mqttPort = mqttPort;
this.mqttUser = mqttUser;
this.mqttPassword = mqttPassword;
this.client = null;
this.isConnected = false;
this.isConnecting = false;
this.reconnectInterval = null;
this.connectCbFunc = () => {
console.log("连接成功!");
};
this.disconnectCbFunc = () => {
console.log("连接断开!");
};
this.errorCbFunc = () => {
console.log("连接错误!");
};
this.heartbeatInterval = null;
this.reconnectCount = 0; // 重连次数
this.maxReconnectCount = 8; // 最大重连次数
this.clientId = "mqtt" + new Date().getTime().toString();
}
// 连接MQTT
connect(connectCbFunc, disconnectCbFunc, errorCbFunc) {
this.connectCbFunc = connectCbFunc;
this.disconnectCbFunc = disconnectCbFunc;
this.errorCbFunc = errorCbFunc;
if (!this.isConnecting && !this.isConnected) {
console.log("MQTT: Connecting...");
this.isConnecting = true;
this._connect();
}
}
// MQTT连接成功后的回调
_connect() {
try {
this.client = mqtt.connect(`ws://${this.mqttServer}:${this.mqttPort}`, {
username: this.mqttUser,
password: this.mqttPassword,
clientId: this.clientId,
});
this.client.on("connect", () => {
console.log("MQTT: Connected");
this.isConnected = true;
this.isConnecting = false;
this._startHeartbeat();
this.connectCbFunc();
this.reconnectCount = 0;
});
this.client.on("disconnect", () => {
console.log("MQTT: Disconnected");
this.isConnected = false;
this.disconnectCbFunc();
this.reconnect();
});
this.client.on("error", (err) => {
console.error("MQTT: Error", err);
this.errorCbFunc(err);
this.reconnect();
});
} catch (err) {
console.error("MQTT: Failed to connect", err);
this.errorCbFunc(err);
this.reconnect();
}
}
// 重连
reconnect() {
if (this.isConnected || this.isConnecting) {
return;
}
console.log("MQTT: Reconnecting...");
clearInterval(this.reconnectInterval);
this._stopHeartbeat();
if (this.reconnectCount < this.maxReconnectCount) {
this.reconnectInterval = setInterval(() => {
console.log("MQTT: Attempting to reconnect...");
this.client.reconnect();
this.reconnectCount++;
}, 5000);
} else {
console.warn("MQTT: Reach max reconnect count, stop reconnecting...");
}
}
// 发布一条消息到指定主题
publish(mqttTopic, payload) {
if (!this.client || !this.isConnected) {
console.warn(
"MQTT: Can not publish message, MQTT client is not connected"
);
return;
}
this.client.publish(mqttTopic, payload);
}
// 订阅指定主题
subscribe(mqttTopic, cbFunc) {
if (!this.client || !this.isConnected) {
console.warn(
"MQTT: Can not subscribe topic, MQTT client is not connected"
);
return;
}
this.client.subscribe(mqttTopic, cbFunc);
}
// 取消订阅指定主题
unsubscribe(mqttTopic) {
if (!this.client || !this.isConnected) {
console.warn(
"MQTT: Can not unsubscribe topic, MQTT client is not connected"
);
return;
}
this.client.unsubscribe(mqttTopic);
}
// 断开与MQTT服务端的连接
disconnect() {
if (!this.client || !this.isConnected) {
console.warn("MQTT: Can not disconnect, MQTT client is not connected");
return;
}
this._stopHeartbeat();
this.client.end();
}
// 开始心跳检测
_startHeartbeat() {
this.heartbeatInterval = setInterval(() => {
console.log("MQTT: Sending heartbeat...");
this._sendHeartbeat();
}, 30000);
}
// 停止心跳检测
_stopHeartbeat() {
clearInterval(this.heartbeatInterval);
}
// 发送心跳包
_sendHeartbeat() {
if (!this.client || !this.isConnected) {
console.warn(
"MQTT: Can not send heartbeat, MQTT client is not connected"
);
return;
}
const now = new Date().getTime().toString();
this.client.publish("heartbeat", now);
}
// 查看MQTT服务端当前所有主题
getAllTopics(cbFunc) {
if (!this.client || !this.isConnected) {
console.warn(
"MQTT: Can not get all topics, MQTT client is not connected"
);
return;
}
const topics = [];
this.client.on("message", (topic) => {
if (!topics.includes(topic)) {
topics.push(topic);
}
});
this.client.subscribe("#", { qos: 0 }, () => {
setTimeout(() => {
this.client.unsubscribe("#", () => {
console.log("MQTT: All topics received");
cbFunc(topics);
});
}, 3000);
});
}
// 获取已订阅的主题列表
getSubscribeTopics() {
if (!this.client || !this.isConnected) {
console.warn(
"MQTT: Can not get subscriptions, MQTT client is not connected"
);
return;
}
var subscribedTopics = client.subscriptions();
console.log("Subscribed topics:", subscribedTopics);
return subscribedTopics;
}
// 取消所有主题
unsubscribeAll() {
if (!this.client || !this.isConnected) {
console.warn(
"MQTT: Can not unsubscribe All Topics, MQTT client is not connected"
);
return;
}
client.unsubscribe();
}
// 获取MQTT连接状态
getConnectionStatus() {
return {
isConnected: this.isConnected,
isConnecting: this.isConnecting,
reconnectCount: this.reconnectCount,
};
}
// 设置MQTT最大重连次数
setMaxReconnectCount(maxReconnectCount) {
this.maxReconnectCount = maxReconnectCount;
}
// 设置MQTT的clientId
setClientId(clientId) {
this.clientId = clientId;
}
// 获取MQTT连接时长
getConnectionTime() {
if (!this.isConnected) {
return 0;
}
const connectionTime =
new Date().getTime() - this.client.options.connectTime;
return connectionTime;
}
// 获取MQTT Ping值
getPingTime() {
if (!this.isConnected) {
return 0;
}
return this.client.pingRTT;
}
}
export default Mqtt;