ruoyi-geek-App/plugins/mqttclient.ts

165 lines
5.5 KiB
TypeScript
Raw Normal View History

2025-11-24 14:57:53 +00:00
import { generateUUID } from "@/utils/geek";
import * as mqtt from "mqtt/dist/mqtt";
const enableJSONDecoding = true // 开启JSON解析消息需要开启JSON解析消息才能开启uuid和event
const enableJSONEncoding = true // 开启JSON消息编码
const enableUUID = true // 需要接收信息中包含uuid字段uuid优先级高于event
type MqttConnectOptions = {
clean: boolean,
connectTimeout: number,
clientId: string, // 认证信息
keepalive: number,
protocolId?: string, // 默认 'MQTT'
protocolVersion?: number, // 默认4
username?: string,
password?: string,
}
type MqttConnectConfig = {
url?: string,
options: MqttConnectOptions
}
interface MqttClient {
connected:boolean,
on: {
(event: "connect", fun: () => void): void;
(event: "reconnect", fun: () => void): void;
(event: "disconnect", fun: () => void): void;
(event: "offline", fun: () => void): void;
(event: "message", fun: (topic: string, message: any, packet?: any) => void): void;
(event: "packetsend", fun: (packet: any) => void): void;
(event: "packetreceive", fun: (packet: any) => void): void;
(event: "error", fun: (err: any) => void): void;
};
publish: {
(topic: string, message: any, options?: any, callback?: (err: any) => void): void;
}
subscribe: {
(topic: string, options?: any, callback?: (err: any, granted: { topic: string, qos: any }) => void): void
}
unsubscribe: {
(topic: string, callback?: (err: any) => void): void
}
end(force?:boolean, options?:any, callback?: (err: any) => void): void
}
let _client: MqttClient;
let _callback: { [key: string]: (data: any) => void } = {}
let onmassage = (topic:string,message:string)=>{}
export default {
/**
* websocket
* {url:"ws://demo"}
*
*/
connect(config: MqttConnectConfig) {
return new Promise<void>((resolve, reject) => {
if(!_client || !_client.connected){
_client = mqtt.connect(config.url, config.options);
_client.on('connect', resolve);
_client.on('error', reject);
_client.on('message', (topic,message) => {
if (enableJSONDecoding) {
let data = JSON.parse(message)
if (enableUUID && (data || {}).uuid !== undefined) {
_callback[data.uuid](data)
delete _callback[data.uuid]
}
}
onmassage(topic,message)
})
}
})
},
/**
*
* @param msg json字符串
* @param uuid ,uuidtrue自动生成uuidflase表示该消息不需要单独处理
* @returns
*/
send(topic: string, msg: any, uuid: string | boolean = false, options: any = undefined) {
return new Promise((resolve, reject) => {
const useUUID = enableUUID && uuid != undefined && uuid != "" && uuid != false
if (useUUID) {
if (uuid === true) {
msg.uuid = generateUUID()
_callback[msg.uuid] = resolve
} else {
_callback[uuid] = resolve
}
}
if(enableJSONEncoding){
msg = JSON.stringify(msg)
}
_client.publish(topic, msg, options, err => {
if (err) {
reject(err)
} else if (uuid === false) {
resolve(err)
}
})
})
},
/**
*
* @returns Promise
*/
close(force?: boolean, options?: any, callback?: (err: any) => void) {
return new Promise<void>((resolve, reject) => {
_client.end(force,options,()=>{
resolve()
})
})
},
/**
*
* @param event
* @returns
*/
subscribe(topic: string, options: string | undefined = undefined) {
return new Promise<void>((resolve, reject) => {
_client.subscribe(topic, options, err => {
if (err) {
reject(err)
} else {
resolve()
}
})
})
},
/**
*
* @param event
*/
unsubscribe(topic: string) {
return new Promise<void>((resolve, reject) => {
_client.unsubscribe(topic, err => {
if (err) {
reject(err)
} else {
resolve()
}
})
})
},
/**
*
* @param callback
*/
onMessage(callback: (topic:string,message:string) => void) {
onmassage = callback
},
/**
*
* @param callback
*/
onError(callback: (data: any) => void) {
_client.on('error', callback)
},
/**
*
* @param callback
*/
onClose(callback: () => void) {
_client.on('disconnect', callback)
}
}