Git Product home page Git Product logo

nest-mqtt's Introduction

Nest-MQTT

Description

A MQTT module for Nest.js. Compatible with emqtt.

Installation

⚠️ After version 0.2.0, nest-mqtt make a breaking change. User should add additional mqtt package manual.

$ npm install nest-mqtt mqtt --save

Usage

Import

Nest-mqtt will register as a global module.

You can import with configuration

// app.module.ts
import { Module } from '@nestjs/common';
import { MqttModule } from 'nest-mqtt';

@Module({
  imports: [MqttModule.forRoot(options)]
})
export class AppModule {}

or use async import method

// app.module.ts
import { Module } from '@nestjs/common';
import { MqttModule } from 'nest-mqtt';

@Module({
  imports: [MqttModule.forRootAsync({
    useFactory: () => options,
  })]
})
export class AppModule {}

Subscribe

You can define any subscriber or consumer in any provider. For example,

import { Injectable } from '@nestjs/common';
import { Subscribe, Payload, Topic } from 'nest-mqtt';

@Injectable()
export class TestService {
  @Subscribe('test')
  test() {
  
  }
  
  @Subscribe({
    topic: 'test2',
    transform: payload => payload.toString(),
  })
  test2() {
    
  }
}

Also, you can inject parameter with decorator:

import { Injectable } from '@nestjs/common';
import { Subscribe, Payload } from 'nest-mqtt';

@Injectable()
export class TestService {
  @Subscribe('test')
  test(@Payload() payload) {
    console.log(payload);
  }
}

Here are all supported parameter decorators:

Payload(transform?: (payload) => any)

Get the payload data of incoming message. You can pass in a transform function for converting.

Topic()

Get the topic of incoming message.

Packet()

Get the raw packet of incoming message.

Params()

Get the wildcard part of topic. It will return an array of string which extract from topic. For example:

When subscribe the topic "test/+/test/+" and incoming topic is "test/1/test/2", you will get the array ["1", "2"].

Publish

Nest-mqtt wrap some functions with Promise and provide a provider.

import { Inject, Injectable } from '@nestjs/common';
import { MqttService } from 'nest-mqtt';

@Injectable()
export class TestService {
  constructor(
    @Inject(MqttService) private readonly mqttService: MqttService,
  ) {}

  async testPublish() {
    this.mqttService.publish('topic', {
      foo: 'bar'
    });
  }

}

Emqtt Compatible

nest-mqtt support emq shared subscription

  • Global mode

Module options support queue and share property for globally converting all topic to shared topic except configured in subscription options.

// app.module.ts
import { Module } from '@nestjs/common';
import { MqttModule } from 'nest-mqtt';

@Module({
  imports: [MqttModule.forRoot({
    host: '127.0.0.1',
    queue: true,
    share: 'group1'
  })]
})
export class AppModule {}
  • Configure in Subscribe
import { Injectable } from '@nestjs/common';
import { Subscribe, Payload, Topic } from 'nest-mqtt';

@Injectable()
export class TestService {
  @Subscribe('test')
  test() {
  
  }
  
  @Subscribe({
    topic: 'test2',
    queue: true,
  })
  test2() {
    
  }
}

The priority of subscribe is higher than the global mode. If you want to specify a topic do not use the shared mode, set it as false in subscribe decorator.

Support

Nest-mqtt is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please read more here.

Stay in touch

License

nest-mqtt is MIT licensed.

nest-mqtt's People

Contributors

jeniturtle avatar microud avatar shenqidebaozi avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

nest-mqtt's Issues

Multiple `MqttModule.forRoot()` global instances

In my use case, I need two global MQTT clients: one using MQTT protocol, the other using websockets.

I added the following into app.module.ts:

@Module({
  imports: [
    MqttModule.forRoot({
      port: 1883,
      logger: {
        useValue: new Logger('MqttClient')
      }
    }),
    MqttModule.forRoot({
      protocol: 'ws',
      port: 4000,
      logger: {
        useValue: new Logger('MqttClientWs')
      }
    })
  ],
})

Now, in the service (@Inject(MqttService) private readonly mqttService: MqttService), how can I differentiate between them?

Support for newer @nestjs/common

I can't install this package, because of unsupported @nestjs/common package version

npm ERR! code ERESOLVE npm ERR! ERESOLVE unable to resolve dependency tree npm ERR! npm ERR! While resolving: [email protected] npm ERR! Found: @nestjs/[email protected] npm ERR! node_modules/@nestjs/common npm ERR! @nestjs/common@"^10.0.0" from the root project npm ERR! npm ERR! Could not resolve dependency: npm ERR! peer @nestjs/common@"^6.10.11 || ^7.0.0 || ^8.0.0" from [email protected] npm ERR! node_modules/nest-mqtt npm ERR! nest-mqtt@"*" from the root project npm ERR! npm ERR! Fix the upstream dependency conflict, or retry npm ERR! this command with --force or --legacy-peer-deps npm ERR! to accept an incorrect (and potentially broken) dependency resolution.

issue in nestjs 8

can't use in newest version

ERROR [ExceptionHandler] Nest can't resolve dependencies of the MqttExplorer (DiscoveryService, MetadataScanner, MQTT_LOGGER_PROVIDER, ?, MQTT_CLIENT_INSTANCE, MQTT_OPTION_PROVIDER). Please make sure that the argument Reflector at index [3] is available in the MqttModule context.

Potential solutions:

  • If Reflector is a provider, is it part of the current MqttModule?
  • If Reflector is exported from a separate @module, is that module imported within MqttModule?
    @module({
    imports: [ /* the Module containing Reflector */ ]
    })

Nest cannot export a provider/module that is not a part of the currently processed module (MqttModule). Please verify whether the exported MqttService is available in this particular context.

Here's my code:

// app.module.ts

//my imports...
import { MqttModule } from 'nest-mqtt';

@Module({
  imports: [
// All my other modules
    MqttModule,
  ],
})

And I got these errors:

3:38:38 pm - Starting compilation in watch mode...
[1]
[0] [nodemon] 2.0.4
[0] [nodemon] to restart at any time, enter `rs`
[0] [nodemon] watching path(s): dist\**\*       
[0] [nodemon] watching extensions: js
[0] [nodemon] starting `node dist/main`
[0] [Nest] 21736   - 04/10/2021, 3:38:43 pm   [NestFactory] Starting Nest application...
[0] [Nest] 21736   - 04/10/2021, 3:38:44 pm   [ExceptionHandler] Nest cannot export a provider/module that is not a part of the currently processed module (MqttModule). Please verify whether the exported MqttService is available in this particular context.
[0]
[0] Possible Solutions:
[0] - Is MqttService part of the relevant providers/imports within MqttModule?
[0]  +65ms
[0] Error: Nest cannot export a provider/module that is not a part of the currently processed module (MqttModule). Please verify whether the exported MqttService is available in this particular context.
[0]
[0] Possible Solutions:
[0] - Is MqttService part of the relevant providers/imports within MqttModule?
[0]
[0]     at Module.validateExportedProvider (C:\Users\User\Projects\MyProject\node_modules\@nestjs\core\injector\module.js:272:19)
[0]     at addExportedUnit (C:\Users\User\Projects\MyProject\node_modules\@nestjs\core\injector\module.js:239:67)
[0]     at Module.addExportedProvider (C:\Users\User\Projects\MyProject\node_modules\@nestjs\core\injector\module.js:250:9)
[0]     at NestContainer.addExportedProvider (C:\Users\User\Projects\MyProject\node_modules\@nestjs\core\injector\container.js:122:19)
[0]     at DependenciesScanner.insertExportedProvider (C:\Users\User\Projects\MyProject\node_modules\@nestjs\core\scanner.js:209:24)
[0]     at C:\Users\User\Projects\MyProject\node_modules\@nestjs\core\scanner.js:117:50
[0]     at Array.forEach (<anonymous>)
[0]     at DependenciesScanner.reflectExports (C:\Users\User\Projects\MyProject\node_modules\@nestjs\core\scanner.js:117:17)
[0]     at DependenciesScanner.scanModulesForDependencies (C:\Users\User\Projects\MyProject\node_modules\@nestjs\core\scanner.js:69:18)
[0]     at processTicksAndRejections (internal/process/task_queues.js:95:5)
[0] [nodemon] app crashed - waiting for file changes before starting...

`nest-mqtt` does not work over websockets

Is it possible to connect to MQTT broker running over websockets? It seems like it cannot detect such a broker.

I created a broker as follows.

const aedes = require('aedes')()
const {createServer} = require('aedes-server-factory')
const server = createServer(aedes, {ws: true})
const port = 1883
server.listen(port, () => {
  console.log('Server started and listening on port ' + port + '.')
})

Issue when publishing binary buffer or Uint8Array

When trying to publish a proto binary buffer the object is converted to JSON string, but it should be published as it is since the client supports buffer / Uint8Array

One way to do it is to change the condition as follow:

  if (typeof message === 'object' && !Buffer.isBuffer(message)) {
    message = JSON.stringify(message);
  }

Is it possible to apply this change ?
Thanks
Andrea

Code from mqtt.service.ts :

  publish(topic: string, message: string | Buffer | object, opts?: IClientPublishOptions): Promise<Packet> {
    return new Promise<Packet>((resolve, reject) => {
      if (typeof message === 'object') {
        message = JSON.stringify(message);
      }
      this.client.publish(topic, message, opts || null, (error, packet) => {
        if (error) {
          reject(error);
        } else {
          resolve(packet);
        }
      });
    });
  }

Tried to publish but returned TypeError: this.mqttService.publish is not a function

  constructor(
    @Inject(MqttService) private readonly mqttService: MqttService,
  ) {}

  @Subscribe('/iot/test/#')
  test(@Payload() payload) {
    console.log(payload)
    try {
      this.mqttService.publish("/test", {a: 1}, { qos: 0 })
    } catch (err) {
      console.error(err)
    }
  }

return this

TypeError: this.mqttService.publish is not a function
    at TestService.test (/Volumes/SSD/Development/nestjs/lege-iot-nest/dist/mqtt/service/TestService.js:25:30)
    at MqttClient.<anonymous> (/Volumes/SSD/Development/nestjs/lege-iot-nest/node_modules/[email protected]@nest-mqtt/dist/mqtt.explorer.js:120:64)
    at MqttClient.emit (events.js:315:20)
    at MqttClient._handlePublish (/Volumes/SSD/Development/nestjs/lege-iot-nest/node_modules/[email protected]@mqtt/lib/client.js:1271:12)
    at MqttClient._handlePacket (/Volumes/SSD/Development/nestjs/lege-iot-nest/node_modules/[email protected]@mqtt/lib/client.js:410:12)
    at work (/Volumes/SSD/Development/nestjs/lege-iot-nest/node_modules/[email protected]@mqtt/lib/client.js:321:12)
    at Writable.writable._write (/Volumes/SSD/Development/nestjs/lege-iot-nest/node_modules/[email protected]@mqtt/lib/client.js:335:5)
    at doWrite (/Volumes/SSD/Development/nestjs/lege-iot-nest/node_modules/[email protected]@readable-stream/lib/_stream_writable.js:428:64)
    at writeOrBuffer (/Volumes/SSD/Development/nestjs/lege-iot-nest/node_modules/[email protected]@readable-stream/lib/_stream_writable.js:417:5)
    at Writable.write (/Volumes/SSD/Development/nestjs/lege-iot-nest/node_modules/[email protected]@readable-stream/lib/_stream_writable.js:334:11)
    at Socket.ondata (_stream_readable.js:707:22)
    at Socket.emit (events.js:315:20)
    at addChunk (_stream_readable.js:296:12)
    at readableAddChunk (_stream_readable.js:272:9)
    at Socket.Readable.push (_stream_readable.js:213:10)
    at TCP.onStreamRead (internal/stream_base_commons.js:186:23)

multiple mqtt clients using forRootAsync

Hi there!

In my project I am using more than one mqtt clients, each client is created by one specific module. It works fine when I'm using forRoot method.

However, when I switched to forRootAsync method, only the first module worked, other clients did not init. I tried to load the modules dynamically, but I got the same result. Where could be wrong?

In my app.module.ts:

@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,
      expandVariables: true,
    }),
    Module1,
    Module2,
    Module3,
    Module4
  ]
})

Only Module1 worked.

Tried to publish a string but received an error

Hi there, would like to ask why would I get this error when I try to publish a string? Here attached are the errors stated in command prompt:

SyntaxError: Unexpected token è in JSON at position 0
at JSON.parse ()
at exports.JsonTransform (C:\Users\user\test-nestjs\node_modules\nest-mqtt\dist\mqtt.transform.js:4:17)
at C:\Users\user\test-nestjs\node_modules\nest-mqtt\dist\mqtt.explorer.js:108:36
at Array.map ()
at MqttClient. (C:\Users\user\test-nestjs\node_modules\nest-mqtt\dist\mqtt.explorer.js:105:82)
at MqttClient.emit (events.js:311:20)
at MqttClient._handlePublish (C:\Users\user\test-nestjs\node_modules\nest-mqtt\node_modules\mqtt\lib\client.js:1162:12)
at MqttClient._handlePacket (C:\Users\user\test-nestjs\node_modules\nest-mqtt\node_modules\mqtt\lib\client.js:351:12)
at work (C:\Users\user\test-nestjs\node_modules\nest-mqtt\node_modules\mqtt\lib\client.js:283:12)
at Writable.writable._write (C:\Users\user\test-nestjs\node_modules\nest-mqtt\node_modules\mqtt\lib\client.js:294:5)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.