2

I am integrating MQTT-adonis module adonis-mqtt respo on git here in adonis-js application while serving it throws an exception

TypeError: instance[method].bind is not a function

Can any one guide why this is appearing.

//event.js

'use strict'
 const Event = use('Event');
const Mqtt = use('Mqtt');
// Listen to some Events of the library
Event.on('MQTT:Connected', 'Message.subscription')
Event.on('MQTT:Disconnected', 'Message.disconnected')

//Listeners/Message.js

class Message extends MqttListener {

get subscription () {
return 'Topic/Info'
 }

async handleMessage (message, wildcardMatches) {
  }

it appears that it is throwing exception here in this block

//node_modules/adonis-mqtt/Mqtt/Mqtt.js

this.client.on('connect', this._handleConnect.bind(this)) //here at this line
    this.client.on('offline', this._handleDisconnect.bind(this))
    this.client.on('close', this._handleDisconnect.bind(this))
    this.client.on('end', this._handleDisconnect.bind(this))
    this.client.on('message', this._handleMessage.bind(this))

EDIT:::

How to reproduce this:

pre-requisite:

  • Node JS latest version (here)
  • Adonis Js latest versions (here)

clone this:

Update:

while removing get from subscription function, it works with no error, but I am unable to get the required data in following code snippet

//node_modules/adonis-mqtt/Mqtt/Mqtt.js

async _registerListener (file) {
    const filePath = path.join(this.listenersPath, file)
    let task
    try {
      task = require(filePath)
    } catch (e) {
      if (e instanceof ReferenceError) {
        debug(
          'Unable to import task class <%s>. Is it a valid javascript class?',
          file)
        return
      } else {
        throw e
      }
    }

    // Get instance of task class
    const taskInstance = ioc.make(task)
    if (!taskInstance.subscription || taskInstance.subscription === '') {
      console.error(`MqttListener ${file} does not have a subscription string!`)
    } else {
      this.client.subscribe(taskInstance.subscription) // here
      debug('Subscribed to topic %s', taskInstance.subscription)
      console.log('Subscribed to topic %s', taskInstance.subscription)
      this.listeners.push(taskInstance)
    }
  }

Update: 2

There are two folders in app one is Listeners and other is MqttListeners, thse both have same named file Test.js, it is also forcing to keep both files. However changes in file exist in Listener folder doesnt make any impact. However removing get prefix from subscription function and console messages in handleMessage() from MqttListners folder's file is seems to be perfect. Receiving published topics info

trighati
  • 1,176
  • 7
  • 19
  • 49

1 Answers1

3

Your problems is here

// events.js
Event.on('MQTT:Connected', 'Message.subscription')

By this, you're binding Message.subscription method to MQTT:Connected event (actually, this happens in node_modules/@adonisjs/fold/src/Ioc/index.js#L879).

However, your Message.subscription is not a normal function but getter. You cannot bind getters because this method syntax doesn't use function expressions.

So, in order to fix your problem you should either bind MQTT:Connected event to some other method i.e.

// events.js
Event.on('MQTT:Connected', 'Message.connection')

// Listeners/Message.js
class Message extends MqttListener {
  connection() {
     return 'test/#';
  }
}

or simply remove get prefix from your subscription method

// Listeners/Message.js
class Message extends MqttListener {

  subscription () {
    return 'test/#';
  }
}

Please let me know if my answer is not clear enough or you need some additional information.

UPDATE: See some proof that it works Screenshot of the fix

Sergey Mell
  • 6,724
  • 1
  • 20
  • 45
  • error gone. earlier mistakenly removed get from another class – trighati Jan 03 '20 at 06:19
  • Great. Let me know if any additional help required – Sergey Mell Jan 03 '20 at 06:26
  • yes I need. Now the mqtt is connected and subscribed all of topics as I have set it to #, how would I get the topic messages in my controller – trighati Jan 03 '20 at 06:28
  • something like this -- `Event.on('MQTT:onMessage', 'Test.handleMessage')` – trighati Jan 03 '20 at 06:31
  • As I understand (I'm not very familar with AdonisJS and mqtt module) and according to the docs (https://github.com/Morlack/adonis-mqtt/blob/HEAD/instructions.md#sending-messages) you can use whatever event name i.e. `Mqtt.sendMessage('mytopic', 'My Message', {qos: 1})` and handle it in similar manner `async handleMessage (message, wildcardMatches) {}` where the first argument is the message data. If you're using thirdparty service you should use their docs in order to get the messages name. I can help if you provide me with this information. – Sergey Mell Jan 03 '20 at 06:42
  • this subscription function is actually returning the topic names, provided in return, if I remove getter, I am unable to get topic names – trighati Jan 03 '20 at 07:05
  • here in this code snippet `this.client.subscribe(taskInstance.subscription) debug('Subscribed to topic %s', taskInstance.subscription) console.log('Subscribed to topic %s', taskInstance.subscription) this.listeners.push(taskInstance)` in this //node_modules/adonis-mqtt/Mqtt/Mqtt.js – trighati Jan 03 '20 at 07:06
  • you were also right.. there is a confusion in folders, two folders must exists with same file `Test.js`, one is `Listeners` and other is `MqttListners` should have `get` before `subscription`. – trighati Jan 03 '20 at 07:27
  • Yes, exactly mqtt listeners should be defined in `app/MqttListeners` and `subscription` is a special method used for defining [MQTT wildcard format](https://github.com/Morlack/adonis-mqtt/blob/HEAD/instructions.md#listeners). However, for handling messages you can use [simple adonis listeners](https://adonisjs.com/docs/4.1/events#_events_overview) as you do now. – Sergey Mell Jan 03 '20 at 08:34
  • How can I pass data to this subscription method, I want to pass user id with text, but I am unable to do. – trighati Jan 13 '20 at 11:53