TypeScript 编写的 MQTT 客户端类,包含订阅、发送消息、心跳和断开连接的方法
1,首先安装mqtt
npm install mqtt
2,然后,你可以创建一个 MqttClient.ts
文件,内容如下:
import mqtt, { MqttClient as MqttClientType, IClientOptions } from 'mqtt';
interface MqttClientConfig {
host: string;
endpoint: string;
clientId: string;
username: string;
password: string;
keepalive: number;
cleanSession: boolean;
connectTimeout: number;
}
class MqttClient {
private client: MqttClientType;
private keepAliveInterval: NodeJS.Timeout | null = null;
private heartbeatTopic: string = '$heartbeat';
constructor(config: MqttClientConfig) {
const { host, endpoint, clientId, username, password, keepalive, cleanSession, connectTimeout } = config;
// MQTT 连接选项
const options: IClientOptions = {
clientId,
username,
password,
keepalive,
clean: cleanSession,
connectTimeout,
will: {
topic: this.heartbeatTopic,
payload: 'Client disconnected',
qos: 0,
},
};
// 连接到 MQTT 代理
this.client = mqtt.connect(`mqtt://${host}${endpoint}`, options);
this.client.on('connect', () => {
console.log('Connected to MQTT broker.');
});
this.client.on('error', (err) => {
console.error('Connection error:', err);
});
this.client.on('message', (topic, message) => {
console.log(`Received message '${message.toString()}' on topic '${topic}'`);
});
this.client.on('close', () => {
console.log('Connection closed.');
});
}
/**
* 订阅一个主题
* @param topic 主题名称
* @param callback 消息处理函数
*/
public subscribe(topic: string, callback: (topic: string, message: Buffer) => void): void {
this.client.subscribe(topic, (err) => {
if (err) {
console.error(`Failed to subscribe to ${topic}:`, err);
} else {
console.log(`Subscribed to ${topic}`);
this.client.on('message', callback);
}
});
}
/**
* 发布消息
* @param topic 主题名称
* @param message 消息内容
* @param qos 服务质量等级
*/
public publish(topic: string, message: string, qos: number = 0): void {
this.client.publish(topic, message, { qos }, (err) => {
if (err) {
console.error(`Failed to publish message to ${topic}:`, err);
} else {
console.log(`Message published to ${topic}`);
}
});
}
/**
* 启动心跳机制
* @param interval 心跳间隔(秒)
*/
public startHeartbeat(interval: number = 60): void {
if (this.keepAliveInterval !== null) {
console.warn('Heartbeat already started.');
return;
}
this.keepAliveInterval = setInterval(() => {
if (this.client.connected) {
this.publish(this.heartbeatTopic, 'heartbeat');
}
}, interval * 1000);
}
/**
* 停止心跳机制
*/
public stopHeartbeat(): void {
if (this.keepAliveInterval !== null) {
clearInterval(this.keepAliveInterval);
this.keepAliveInterval = null;
console.log('Heartbeat stopped.');
}
}
/**
* 断开连接
*/
public disconnect(): void {
this.client.end(true, () => {
console.log('Disconnected from MQTT broker.');
});
}
}
export default MqttClient;
到这一步就已经完成了
3,在 src
目录下创建一个 mqttProvider.ts
文件,用于设置 MQTT 客户端的提供者。
在 Vue 3 中,你可以使用全局状态管理来确保 MQTT 客户端只连接一次,并在多个页面之间共享这个连接。下面是一个
import { reactive, provide, inject } from 'vue';
import MqttClient, { MqttClientConfig } from './MqttClient';
const MQTT_CLIENT_SYMBOL = Symbol('MqttClient');
/**
* 创建 MQTT 客户端实例并提供
* @param config MQTT 配置对象
* @returns 客户端实例及其符号
*/
export function createMqttClient(config: MqttClientConfig) {
const mqttClient = new MqttClient(config);
const state = reactive({ client: mqttClient });
return {
mqttClient: state,
MQTT_CLIENT_SYMBOL,
};
}
/**
* 获取 MQTT 客户端实例
* @returns MQTT 客户端实例
*/
export function useMqttClient() {
const mqttClient = inject(MQTT_CLIENT_SYMBOL);
if (!mqttClient) {
throw new Error('No MqttClient provided!');
}
return mqttClient as { client: MqttClient };
}
示例:使用 Vue 3 的 provide
和 inject
功能来实现这一点的示例:
在 App.vue
中,提供 MQTT 客户端配置。
<template>
<router-view />
</template>
<script setup>
import { createMqttClient } from './mqttProvider';
const mqttConfig = {
host: '',//地址
endpoint: '/mqtt',
clientId: 'your-client-id',
username: 'your-username',
password: 'your-password',
keepalive: 60,
cleanSession: false,
connectTimeout: 5000,
};
// 创建并提供 MQTT 客户端实例
const { mqttClient, MQTT_CLIENT_SYMBOL } = createMqttClient(mqttConfig);
// 提供 MQTT 客户端实例给 Vue 组件
provide(MQTT_CLIENT_SYMBOL, mqttClient);
</script>
子组件中获取并使用 MQTT 客户端实例:
<template>
<div>
<button @click="sendMessage">Send Message</button>
</div>
</template>
<script setup>
import { useMqttClient } from '../mqttProvider';
const { client } = useMqttClient();
function sendMessage() {
client.publish('test/topic', 'Hello from Vue!');
}
// 启动心跳(可选)
// client.startHeartbeat();
// 停止心跳(可选)
// client.stopHeartbeat();
// 断开连接(可选)
// client.disconnect();
</script>