mm_os
Version:
这是超级美眉服务端框架,用于快速构建应用程序。
330 lines (306 loc) • 6.95 kB
JavaScript
const MQTT = require('mqtt');
const {
v4
} = require('uuid');
class MM_mqtt {
/**
* 构造函数
* @param {Object} config 配置参数
*/
constructor(config) {
var clientId = v4();
this.config = Object.assign({
hostname: "127.0.0.1",
port: "",
protocol: "ws",
clientId,
subscribe_qos: 0,
publish_qos: 1,
username: "demo",
password: "asd123",
clean: false,
topic_receive: "client/message/",
longtime: 15000,
// maxInflight: 20,
// 重连间隔时间,单位为毫秒, 默认6秒
reconnectPeriod: 6000,
// 连接超时时间,单位为毫秒, 默认30秒, 即尝试连接5次
connectTimeout: 30000
}, config);
// mqtt客户端服务器
this.client = null;
/**
* message queue
*/
this.list_msg = [
/*
{
// information ID
id: "",
// request method
method: "",
// message parameters
params: {},
// Callback
func: function(res){}
}
*/
];
/**
* 订阅集合 (主题 => 函数列表)
*/
this.dict_subscribe = {};
/**
* method collection
*/
this.methods = {
/**
* Provide to the server to see how many open functions there are
*/
get_method: function() {
return Object.keys(_this.methods)
}
};
this.retryTimes = 0;
this.connecting = false;
}
}
/**
* 重新连接
*/
MM_mqtt.prototype.reconnect = function() {
this.retryTimes += 1;
if (this.retryTimes > 5) {
try {
this.client.end();
setTimeout(() => {
this.init();
}, this.config.reconnectPeriod);
} catch (error) {
this.$message.error(error.toString());
}
}
}
/**
* 初始化
* @param {Object} config 配置参数
*/
MM_mqtt.prototype.init = function(config) {
this.config = Object.assign(this.config, config);
this.client = {
connected: false,
};
this.retryTimes = 0;
this.connecting = false;
};
/**
* 运行MQTT
*/
MM_mqtt.prototype.run = function(config) {
this.connecting = true;
var err;
try {
var cg = Object.assign(this.config, config);
if (cg.host) {
delete cg.hostname;
delete cg.port;
this.client = MQTT.connect(cg.host, cg);
} else {
this.client = MQTT.connect(cg);
}
if (this.client.on) {
return new Promise((resolve, reject) => {
this.client.on('connect', (packet, err) => {
this.connecting = false;
if (err) {
resolve(null);
reject(err);
} else {
this.client.on('message', async (topic, message) => {
await this.receive(topic, message.toString());
});
resolve(packet);
}
});
this.client.on("reconnect", this.reconnect);
this.client.on("error", (error) => {
console.error("Connection failed", error);
});
});
}
} catch (error) {
this.connecting = false;
err = error;
}
return new Promise((resolve, reject) => {
resolve(null);
reject(err);
});
};
/**
* 监听事件
* @param {String} eventName
* @param {Function} func
*/
MM_mqtt.prototype.on = function(eventName, func) {
this.client.on(eventName, func);
};
/**
* 接收消息
* @param {String} topic 订阅板块
* @param {Object} msg 消息主体
*/
MM_mqtt.prototype.message = async function(topic, msg) {
if (this.dict_subscribe[topic]) {
var list = this.dict_subscribe[topic];
try {
for (var key in list) {
list[key](msg);
}
} catch (err) {
console.error(err);
}
}
}
/**
* 接收消息
* @param {String} topic 订阅
* @param {Object} bodyStr 消息主体
*/
MM_mqtt.prototype.receive = async function(topic, bodyStr) {
var json;
if (bodyStr && (bodyStr.indexOf('[') === 0) || bodyStr.indexOf('{') === 0) {
try {
json = JSON.parse(bodyStr);
} catch {}
}
if (json) {
var id = json.id;
if (json.result && id) {
var lt = this.list_msg;
var len = lt.length;
var has = false;
for (var i = 0; i < len; i++) {
var o = lt[i];
if (id === o.id) {
o.func(json.result);
lt.splice(i, 1);
has = true;
break;
}
}
if (has) {
return;
}
} else if (json.method) {
var func;
var methods = this.methods;
var arr = json.method.split('.');
for (var i = 0; i < arr.length; i++) {
var m = methods[arr[i]];
if (m) {
methods = m;
}
}
if (methods && typeof(methods) == 'function') {
func = methods;
}
if (func) {
var params = json.params;
var from = params.from;
var ret = func(params);
if (ret) {
var obj = {};
if (id) {
obj.id = id
}
obj.result = ret;
if (from) {
var topic_receive = this.config.topic_receive + from;
this.send(topic_receive, obj);
}
}
return;
}
}
await this.message(topic, json);
return
}
await this.message(topic, bodyStr);
};
MM_mqtt.prototype.subscribe = function(topic, func, qos = null, retain = false) {
if (qos === null || qos === undefined) {
qos = this.config.subscribe_qos || 0;
}
// console.log("订阅", qos);
this.client.subscribe(topic, {
// 订阅消息方式,0为保留 , 1为确认收到1次
qos,
retain
});
if (func) {
if (!this.dict_subscribe[topic]) {
this.dict_subscribe[topic] = {};
}
var key = this.key_num + 1;
this.dict_subscribe[topic][key] = func;
return key;
}
}
MM_mqtt.prototype.unsubscribe = function(topic, key) {
this.client.unsubscribe(topic);
if (this.dict_subscribe[topic]) {
delete this.dict_subscribe[topic][key];
}
}
MM_mqtt.prototype.end = function() {
this.client.end();
};
MM_mqtt.prototype.publish = function(topic, message, qos = null, retain = false) {
if (qos === null || qos === undefined) {
qos = this.config.publish_qos || 0;
}
// console.log("发布", qos, topic);
this.client.publish(topic, message, {
qos,
retain
});
};
MM_mqtt.prototype.send = function(topic, msgObj) {
this.publish(topic, JSON.stringify(msgObj));
};
MM_mqtt.prototype.req = function(topic, method, params, func) {
var data = {
id: this.client.options.clientId + "_" + Date.parse(new Date()),
method,
params
};
if (func) {
data.func = func;
this.list_msg.push(data);
}
this.send(topic, data);
};
/**
* 同步请求 - 可及时取回消息
* @param {String} method 请求方法
* @param {Object} params 传递参数
* @returns {Object} 返回响应结果
*/
MM_mqtt.prototype.reqASync = function(topic, method, params) {
var _this = this;
return new Promise((resolve, reject) => {
var hasMsg;
_this.req(topic, method, params, (res) => {
hasMsg = true;
resolve(res);
});
setTimeout(function() {
if (!hasMsg) {
resolve(null);
reject("request timeout!");
}
}, 3000);
});
};
module.exports = MM_mqtt;