UNPKG

mm_os

Version:

这是超级美眉服务端框架,用于快速构建应用程序。

330 lines (306 loc) 6.95 kB
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;