UNPKG

@meddv/ngx-mqtt

Version:

This library isn't just a wrapper around MQTT.js for angular. It uses observables and takes care of subscription handling and message routing.

1 lines 31.6 kB
{"version":3,"file":"meddv-ngx-mqtt.mjs","sources":["../../../projects/ngx-mqtt/src/lib/mqtt.model.ts","../../../projects/ngx-mqtt/src/lib/mqtt.module.ts","../../../projects/ngx-mqtt/src/lib/mqtt.service.ts","../../../projects/ngx-mqtt/src/public-api.ts","../../../projects/ngx-mqtt/src/meddv-ngx-mqtt.ts"],"sourcesContent":["import { Stream } from 'stream';\r\nimport {MqttClient, IClientOptions, IClientPublishOptions, IStream, IConnackPacket} from 'mqtt';\r\nimport {IPacket} from \"mqtt-packet\";\r\n\r\nexport enum MqttConnectionState {\r\n CLOSED,\r\n CONNECTING,\r\n CONNECTED\r\n}\r\n\r\nexport interface IMqttServiceOptions extends IClientOptions {\r\n /**\r\n * whether a new connection should be created\r\n * on creating an instance of the service\r\n */\r\n connectOnCreate?: boolean;\r\n /** the hostname of the mqtt broker */\r\n hostname?: string;\r\n /** the port to connect with websocket to the broker */\r\n port?: number;\r\n /** the path parameters to connect to e.g. `/mqtt` */\r\n path?: string;\r\n protocol?: 'wss' | 'ws';\r\n /** if the url is provided, hostname, port path and protocol are ignored */\r\n url?: string;\r\n}\r\n\r\nexport interface IMqttMessage extends IPacket {\r\n /** the mqtt topic to which this message was published to */\r\n topic: string;\r\n /** the payload */\r\n payload: string | Buffer;\r\n /** the quality of service */\r\n qos: number;\r\n /** if this message is a retained message */\r\n retain: boolean;\r\n /** if this message is a duplicate */\r\n dup: boolean;\r\n}\r\n\r\nexport interface IPublishOptions extends IClientPublishOptions { }\r\nexport interface IOnConnectEvent extends IConnackPacket { }\r\nexport interface IOnErrorEvent extends Error {\r\n type?: string;\r\n}\r\nexport interface IOnMessageEvent extends IMqttMessage { }\r\nexport interface IOnSubackEvent {\r\n granted: boolean;\r\n filter: string;\r\n}\r\n\r\nexport interface IMqttClient extends MqttClient {\r\n stream: IStream;\r\n}\r\n\r\nexport interface IOnPacketsendEvent extends IPacket { }\r\nexport interface IOnPacketreceiveEvent extends IPacket { }\r\n","import {\r\n NgModule,\r\n ModuleWithProviders,\r\n InjectionToken\r\n} from '@angular/core';\r\nimport { IMqttClient, IMqttServiceOptions } from './mqtt.model';\r\n\r\nexport const MQTT_SERVICE_OPTIONS: IMqttServiceOptions = {\r\n connectOnCreate: true,\r\n hostname: 'localhost',\r\n port: 1884,\r\n path: ''\r\n};\r\n\r\nexport const MqttServiceConfig = new InjectionToken<IMqttServiceOptions>('NgxMqttServiceConfig');\r\nexport const MqttClientService = new InjectionToken<IMqttClient>('NgxMqttClientService');\r\n\r\n@NgModule()\r\nexport class MqttModule {\r\n static forRoot(config: IMqttServiceOptions, client?: IMqttClient): ModuleWithProviders<MqttModule> {\r\n return {\r\n ngModule: MqttModule,\r\n providers: [\r\n {\r\n provide: MqttServiceConfig,\r\n useValue: config\r\n },\r\n {\r\n provide: MqttClientService,\r\n useValue: client\r\n }\r\n ]\r\n };\r\n }\r\n}\r\n","import { EventEmitter, Inject, Injectable } from '@angular/core';\r\nimport { IClientPublishOptions, IClientSubscribeOptions, ISubscriptionGrant} from 'mqtt';\r\nimport { Packet } from 'mqtt-packet';\r\n\r\nimport mqtt from 'mqtt';\r\nconst connect = mqtt.connect;\r\ntype MqttClient = mqtt.MqttClient;\r\n\r\nimport { BehaviorSubject, merge, Observable, Observer, Subject, Subscription, Unsubscribable, using } from 'rxjs';\r\nimport { filter, publish, publishReplay, refCount } from 'rxjs/operators';\r\n\r\nimport {\r\n IMqttMessage,\r\n IMqttServiceOptions,\r\n IOnConnectEvent,\r\n IOnErrorEvent,\r\n IOnPacketreceiveEvent,\r\n IOnPacketsendEvent,\r\n IOnSubackEvent,\r\n IPublishOptions,\r\n MqttConnectionState\r\n} from './mqtt.model';\r\n\r\nimport { MqttClientService, MqttServiceConfig } from './mqtt.module';\r\n\r\n// A javascript function that takes two objects and merges them recursively\r\nfunction mergeDeep(target: any, ...sources: any[]): any {\r\n if (!sources.length) {\r\n return target;\r\n }\r\n const source = sources.shift();\r\n\r\n if (isObject(target) && isObject(source)) {\r\n for (const key in source) {\r\n if (isObject(source[key])) {\r\n if (!target[key]) {\r\n Object.assign(target, { [key]: {} });\r\n }\r\n mergeDeep(target[key], source[key]);\r\n } else {\r\n Object.assign(target, { [key]: source[key] });\r\n }\r\n }\r\n }\r\n\r\n return mergeDeep(target, ...sources);\r\n}\r\n\r\nfunction isObject(item: any): item is Object {\r\n return item && typeof item === 'object' && !Array.isArray(item);\r\n}\r\n\r\n/**\r\n * With an instance of MqttService, you can observe and subscribe to MQTT in multiple places, e.g. in different components,\r\n * to only subscribe to the broker once per MQTT filter.\r\n * It also handles proper unsubscription from the broker, if the last observable with a filter is closed.\r\n */\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class MqttService {\r\n private client!: MqttClient;\r\n\r\n /**\r\n * The constructor needs [connection options]{@link IMqttServiceOptions} regarding the broker and some\r\n * options to configure behavior of this service, like if the connection to the broker\r\n * should be established on creation of this service or not.\r\n */\r\n constructor(\r\n @Inject(MqttServiceConfig) private options: IMqttServiceOptions,\r\n @Inject(MqttClientService) client?: MqttClient\r\n ) {\r\n if (options.connectOnCreate !== false) {\r\n this.connect({}, client);\r\n }\r\n\r\n this.state.subscribe();\r\n }\r\n\r\n /**\r\n * gets the _clientId\r\n */\r\n public get clientId() {\r\n return this._clientId;\r\n }\r\n\r\n /** An EventEmitter to listen to connect messages */\r\n public get onConnect(): EventEmitter<IOnConnectEvent> {\r\n return this._onConnect;\r\n }\r\n\r\n /** An EventEmitter to listen to reconnect messages */\r\n public get onReconnect(): EventEmitter<void> {\r\n return this._onReconnect;\r\n }\r\n\r\n /** An EventEmitter to listen to close messages */\r\n public get onClose(): EventEmitter<void> {\r\n return this._onClose;\r\n }\r\n\r\n /** An EventEmitter to listen to offline events */\r\n public get onOffline(): EventEmitter<void> {\r\n return this._onOffline;\r\n }\r\n\r\n /** An EventEmitter to listen to error events */\r\n public get onError(): EventEmitter<IOnErrorEvent> {\r\n return this._onError;\r\n }\r\n\r\n /** An EventEmitter to listen to close messages */\r\n public get onEnd(): EventEmitter<void> {\r\n return this._onEnd;\r\n }\r\n\r\n /** An EventEmitter to listen to message events */\r\n public get onMessage(): EventEmitter<Packet> {\r\n return this._onMessage;\r\n }\r\n\r\n /** An EventEmitter to listen to packetsend messages */\r\n public get onPacketsend(): EventEmitter<IOnPacketsendEvent> {\r\n return this._onPacketsend;\r\n }\r\n\r\n /** An EventEmitter to listen to packetreceive messages */\r\n public get onPacketreceive(): EventEmitter<IOnPacketreceiveEvent> {\r\n return this._onPacketreceive;\r\n }\r\n\r\n /** An EventEmitter to listen to suback events */\r\n public get onSuback(): EventEmitter<IOnSubackEvent> {\r\n return this._onSuback;\r\n }\r\n\r\n /** An actual connection state **/\r\n public get connectionState(): MqttConnectionState {\r\n return this.state.value;\r\n }\r\n\r\n /** a map of all mqtt observables by filter */\r\n public observables: { [filterString: string]: Observable<IMqttMessage> } = {};\r\n /** the connection state */\r\n public state: BehaviorSubject<MqttConnectionState> = new BehaviorSubject<MqttConnectionState>(MqttConnectionState.CLOSED);\r\n /** an observable of the last mqtt message */\r\n public messages: Subject<IMqttMessage> = new Subject<IMqttMessage>();\r\n\r\n private _clientId = this._generateClientId();\r\n private _connectTimeout = 10000;\r\n private _reconnectPeriod = 10000;\r\n private _url!: string;\r\n\r\n private _onConnect: EventEmitter<IOnConnectEvent> = new EventEmitter<IOnConnectEvent>();\r\n private _onReconnect: EventEmitter<void> = new EventEmitter<void>();\r\n private _onClose: EventEmitter<void> = new EventEmitter<void>();\r\n private _onOffline: EventEmitter<void> = new EventEmitter<void>();\r\n private _onError: EventEmitter<IOnErrorEvent> = new EventEmitter<IOnErrorEvent>();\r\n private _onEnd: EventEmitter<void> = new EventEmitter<void>();\r\n private _onMessage: EventEmitter<Packet> = new EventEmitter<Packet>();\r\n private _onSuback: EventEmitter<IOnSubackEvent> = new EventEmitter<IOnSubackEvent>();\r\n private _onPacketsend: EventEmitter<IOnPacketsendEvent> = new EventEmitter<IOnPacketsendEvent>();\r\n private _onPacketreceive: EventEmitter<IOnPacketreceiveEvent> = new EventEmitter<IOnPacketreceiveEvent>();\r\n\r\n /**\r\n * This static method shall be used to determine whether a MQTT\r\n * topic matches a given filter. The matching rules are specified in the MQTT\r\n * standard documentation and in the library test suite.\r\n *\r\n * @param {string} filter A filter may contain wildcards like '#' and '+'.\r\n * @param {string} topic A topic may not contain wildcards.\r\n * @return {boolean} true on match and false otherwise.\r\n */\r\n public static filterMatchesTopic(filterString: string, topic: string): boolean {\r\n if (filterString[0] === '#' && topic[0] === '$') {\r\n return false;\r\n }\r\n // Preparation: split and reverse on '/'. The JavaScript split function is sane.\r\n const fs = (filterString || '').split('/').reverse();\r\n const ts = (topic || '').split('/').reverse();\r\n // This function is tail recursive and compares both arrays one element at a time.\r\n const match = (): boolean => {\r\n // Cutting of the last element of both the filter and the topic using pop().\r\n const f = fs.pop();\r\n const t = ts.pop();\r\n switch (f) {\r\n // In case the filter level is '#', this is a match no matter whether\r\n // the topic is undefined on this level or not ('#' matches parent element as well!).\r\n case '#':\r\n return true;\r\n // In case the filter level is '+', we shall dive into the recursion only if t is not undefined.\r\n case '+':\r\n return t ? match() : false;\r\n // In all other cases the filter level must match the topic level,\r\n // both must be defined and the filter tail must match the topic\r\n // tail (which is determined by the recursive call of match()).\r\n default:\r\n return f === t && (f === undefined ? true : match());\r\n }\r\n };\r\n return match();\r\n }\r\n\r\n /**\r\n * connect manually connects to the mqtt broker.\r\n */\r\n public connect(opts?: IMqttServiceOptions, client?: MqttClient) {\r\n const options = mergeDeep(this.options || {}, opts);\r\n const protocol = options.protocol || 'ws';\r\n const hostname = options.hostname || 'localhost';\r\n if (options.url) {\r\n this._url = options.url;\r\n } else {\r\n this._url = `${protocol}://${hostname}`;\r\n this._url += options.port ? `:${options.port}` : '';\r\n this._url += options.path ? `${options.path}` : '';\r\n }\r\n this.state.next(MqttConnectionState.CONNECTING);\r\n const mergedOptions = mergeDeep({\r\n clientId: this._clientId,\r\n reconnectPeriod: this._reconnectPeriod,\r\n connectTimeout: this._connectTimeout\r\n }, options);\r\n\r\n if (this.client) {\r\n this.client.end(true);\r\n }\r\n\r\n if (!client) {\r\n this.client = connect(this._url, mergedOptions);\r\n } else {\r\n this.client = client;\r\n }\r\n this._clientId = mergedOptions.clientId;\r\n\r\n this.client.on('connect', this._handleOnConnect);\r\n this.client.on('reconnect', this._handleOnReconnect);\r\n this.client.on('close', this._handleOnClose);\r\n this.client.on('offline', this._handleOnOffline);\r\n this.client.on('error', this._handleOnError);\r\n (this.client as any).stream.on('error', this._handleOnError);\r\n this.client.on('end', this._handleOnEnd);\r\n this.client.on('message', this._handleOnMessage);\r\n this.client.on('packetsend', this._handleOnPacketsend);\r\n this.client.on('packetreceive', this._handleOnPacketreceive);\r\n }\r\n\r\n /**\r\n * disconnect disconnects from the mqtt client.\r\n * This method `should` be executed when leaving the application.\r\n */\r\n public disconnect(force = true) {\r\n if (!this.client) {\r\n throw new Error('mqtt client not connected');\r\n }\r\n this.client.end(force);\r\n }\r\n\r\n /**\r\n * With this method, you can observe messages for a mqtt topic.\r\n * The observable will only emit messages matching the filter.\r\n * The first one subscribing to the resulting observable executes a mqtt subscribe.\r\n * The last one unsubscribing this filter executes a mqtt unsubscribe.\r\n * Every new subscriber gets the latest message.\r\n */\r\n public observeRetained(filterString: string, opts: IClientSubscribeOptions = { qos: 1 }): Observable<IMqttMessage> {\r\n return this._generalObserve(filterString, () => publishReplay(1), opts);\r\n }\r\n\r\n /**\r\n * With this method, you can observe messages for a mqtt topic.\r\n * The observable will only emit messages matching the filter.\r\n * The first one subscribing to the resulting observable executes a mqtt subscribe.\r\n * The last one unsubscribing this filter executes a mqtt unsubscribe.\r\n */\r\n public observe(filterString: string, opts: IClientSubscribeOptions = { qos: 1 }): Observable<IMqttMessage> {\r\n return this._generalObserve(filterString, () => publish(), opts);\r\n }\r\n\r\n /**\r\n * With this method, you can observe messages for a mqtt topic.\r\n * The observable will only emit messages matching the filter.\r\n * The first one subscribing to the resulting observable executes a mqtt subscribe.\r\n * The last one unsubscribing this filter executes a mqtt unsubscribe.\r\n * Depending on the publish function, the messages will either be replayed after new\r\n * subscribers subscribe or the messages are just passed through\r\n */\r\n private _generalObserve(filterString: string, publishFn: Function, opts: IClientSubscribeOptions): Observable<IMqttMessage> {\r\n if (!this.client) {\r\n throw new Error('mqtt client not connected');\r\n }\r\n if (!this.observables[filterString]) {\r\n const rejected: Subject<IMqttMessage> = new Subject();\r\n this.observables[filterString] = using(\r\n // resourceFactory: Do the actual ref-counting MQTT subscription.\r\n // refcount is decreased on unsubscribe.\r\n () => {\r\n const subscription: Subscription = new Subscription();\r\n this.client.subscribe(filterString, opts, (err: any, granted: ISubscriptionGrant[] | undefined) => {\r\n if (granted) { // granted can be undefined when an error occurs when the client is disconnecting\r\n granted.forEach((granted_: ISubscriptionGrant) => {\r\n if (granted_.qos === 128) {\r\n delete this.observables[granted_.topic];\r\n this.client.unsubscribe(granted_.topic);\r\n rejected.error(`subscription for '${granted_.topic}' rejected!`);\r\n }\r\n this._onSuback.emit({ filter: filterString, granted: granted_.qos !== 128 });\r\n });\r\n }\r\n });\r\n subscription.add(() => {\r\n delete this.observables[filterString];\r\n this.client.unsubscribe(filterString);\r\n });\r\n return subscription;\r\n },\r\n // observableFactory: Create the observable that is consumed from.\r\n // This part is not executed until the Observable returned by\r\n // `observe` gets actually subscribed.\r\n (subscription: Unsubscribable | void) => merge(rejected, this.messages))\r\n .pipe(\r\n filter((msg: IMqttMessage) => MqttService.filterMatchesTopic(filterString, msg.topic)),\r\n publishFn(),\r\n refCount()\r\n ) as Observable<IMqttMessage>;\r\n }\r\n return this.observables[filterString];\r\n }\r\n\r\n /**\r\n * This method returns an observable for a topic with optional options.\r\n * After subscribing, the actual mqtt publication will be executed and\r\n * the observable will emit an empty value and completes, if publishing was successful\r\n * or throws an error, if the publication fails.\r\n */\r\n public publish(topic: string, message: string | Buffer, options: IClientPublishOptions = {}): Observable<void> {\r\n if (!this.client) {\r\n throw new Error('mqtt client not connected');\r\n }\r\n return Observable.create((obs: Observer<void>) => {\r\n this.client.publish(topic, message, options, (error: Error | undefined) => {\r\n if (error) {\r\n obs.error(error);\r\n } else {\r\n obs.next();\r\n obs.complete();\r\n }\r\n });\r\n });\r\n }\r\n\r\n /**\r\n * This method publishes a message for a topic with optional options.\r\n * If an error occurs, it will throw.\r\n */\r\n public unsafePublish(topic: string, message: string | Buffer, options: IPublishOptions = {}): void {\r\n if (!this.client) {\r\n throw new Error('mqtt client not connected');\r\n }\r\n this.client.publish(topic, message, options, (error: Error | undefined) => {\r\n if (error) {\r\n throw (error);\r\n }\r\n });\r\n }\r\n\r\n private _handleOnConnect = (e: IOnConnectEvent) => {\r\n if (this.options.connectOnCreate === true) {\r\n Object.keys(this.observables).forEach((filterString: string) => {\r\n this.client.subscribe(filterString);\r\n });\r\n }\r\n this.state.next(MqttConnectionState.CONNECTED);\r\n this._onConnect.emit(e);\r\n }\r\n\r\n private _handleOnReconnect = () => {\r\n if (this.options.connectOnCreate === true) {\r\n Object.keys(this.observables).forEach((filterString: string) => {\r\n this.client.subscribe(filterString);\r\n });\r\n }\r\n this.state.next(MqttConnectionState.CONNECTING);\r\n this._onReconnect.emit();\r\n }\r\n\r\n private _handleOnClose = () => {\r\n this.state.next(MqttConnectionState.CLOSED);\r\n this._onClose.emit();\r\n }\r\n\r\n private _handleOnOffline = () => {\r\n this._onOffline.emit();\r\n }\r\n\r\n private _handleOnError = (e: IOnErrorEvent) => {\r\n this._onError.emit(e);\r\n console.error(e);\r\n }\r\n\r\n private _handleOnEnd = () => {\r\n this._onEnd.emit();\r\n }\r\n\r\n private _handleOnMessage = (topic: string, payload: Buffer, packet: Packet) => {\r\n this._onMessage.emit(packet);\r\n if (packet.cmd === 'publish') {\r\n this.messages.next(packet as any);\r\n }\r\n }\r\n\r\n private _handleOnPacketsend = (e: IOnPacketsendEvent) => {\r\n this._onPacketsend.emit(e);\r\n }\r\n\r\n private _handleOnPacketreceive = (e: IOnPacketreceiveEvent) => {\r\n this._onPacketreceive.emit(e);\r\n }\r\n\r\n private _generateClientId() {\r\n return 'client-' + Math.random().toString(36).substr(2, 19);\r\n }\r\n}\r\n","/*\r\n * Public API Surface of ngx-mqtt\r\n */\r\n\r\nexport * from './lib/mqtt.model';\r\nexport * from './lib/mqtt.service';\r\nexport * from './lib/mqtt.module';","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}