UNPKG

moleculer

Version:

Fast & powerful microservices framework for Node.JS

212 lines (183 loc) 4.35 kB
/* * moleculer * Copyright (c) 2023 MoleculerJS (https://github.com/moleculerjs/moleculer) * MIT Licensed */ "use strict"; const Transporter = require("./base"); const { isObject } = require("lodash"); const C = require("../constants"); /** * Import types * * @typedef {import("./mqtt")} MqttTransporterClass * @typedef {import("./mqtt").MqttTransporterOptions} MqttTransporterOptions */ /** * Transporter for MQTT * * @class MqttTransporter * @extends {Transporter} * @implements {MqttTransporterClass} */ class MqttTransporter extends Transporter { /** * Creates an instance of MqttTransporter. * * @param {MqttTransporterOptions} opts * * @memberof MqttTransporter */ constructor(opts) { super(opts); this.qos = 0; this.topicSeparator = "."; if (isObject(this.opts)) { if (this.opts.qos !== undefined) { this.qos = this.opts.qos; delete this.opts.qos; } if (this.opts.topicSeparator !== undefined) { this.topicSeparator = this.opts.topicSeparator; delete this.opts.topicSeparator; } } this.client = null; } /** * Connect to the server * * @memberof MqttTransporter */ connect() { return new this.broker.Promise((resolve, reject) => { let mqtt; try { mqtt = require("mqtt"); } catch (err) { /* istanbul ignore next */ this.broker.fatal( "The 'mqtt' package is missing. Please install it with 'npm install mqtt --save' command.", err, true ); } const client = mqtt.connect(this.opts); this._client = client; // For tests client.on("connect", () => { this.client = client; this.logger.info("MQTT client is connected."); this.onConnected().then(resolve); }); /* istanbul ignore next */ client.on("error", e => { this.logger.error("MQTT error.", e.message); this.logger.debug(e); this.broker.broadcastLocal("$transporter.error", { error: e, module: "transporter", type: C.CLIENT_ERROR }); if (!client.connected) reject(e); }); /* istanbul ignore next */ client.on("reconnect", () => { this.logger.warn("MQTT client is reconnecting..."); }); client.on("message", (rawTopic, buf) => { const topic = rawTopic.substring(this.prefix.length + this.topicSeparator.length); const cmd = topic.split(this.topicSeparator)[0]; this.receive(cmd, buf); }); /* istanbul ignore next */ client.on("close", () => { this.connected = false; this.logger.warn("MQTT client is disconnected."); }); }); } /** * Disconnect from the server * * @memberof MqttTransporter */ disconnect() { if (this.client) { return new this.broker.Promise(resolve => { this.client.end(false, resolve); this.client = null; }); } } /** * Get topic name from command & target nodeID * * @param {any} cmd * @param {any} nodeID * * @memberof MqttTransporter */ getTopicName(cmd, nodeID) { return ( this.prefix + this.topicSeparator + cmd + (nodeID ? this.topicSeparator + nodeID : "") ); } /** * Subscribe to a command * * @param {String} cmd * @param {String} nodeID * * @memberof MqttTransporter */ subscribe(cmd, nodeID) { return new this.broker.Promise((resolve, reject) => { const topic = this.getTopicName(cmd, nodeID); this.client.subscribe(topic, { qos: this.qos }, (err, granted) => { if (err) return reject(err); this.logger.debug("MQTT server granted", granted); resolve(); }); }); } /** * Subscribe to balanced action commands * Not implemented. * * @returns {Promise} */ subscribeBalancedRequest() { /* istanbul ignore next */ return this.broker.Promise.resolve(); } /** * Subscribe to balanced event command * Not implemented. * * @returns {Promise} */ subscribeBalancedEvent() { /* istanbul ignore next */ return this.broker.Promise.resolve(); } /** * Send data buffer. * * @param {String} topic * @param {Buffer} data * * @returns {Promise} */ send(topic, data) { /* istanbul ignore next*/ if (!this.client) return; return new this.broker.Promise((resolve, reject) => { this.client.publish(topic, data, { qos: this.qos }, err => { /* istanbul ignore next*/ if (err) return reject(err); resolve(); }); }); } } module.exports = MqttTransporter;