1

I am generating data with a node.js simulator and passing this data to a http route /simulator/data

In the application I am listening broker with MQTT mqtthandler.js file which I share below.

//This is mqtthandler.js file

const mqtt = require("mqtt");

class MqttHandler {
  constructor() {
    this.mqttClient = null;
    this.host = "mqtt://localhost:1883";
    this.username = "YOUR_USER"; // mqtt credentials if these are needed to connect
    this.password = "YOUR_PASSWORD";
  }

  connect() {
    // Connect mqtt with credentials (in case of needed, otherwise we can omit 2nd param)
    this.mqttClient = mqtt.connect(this.host, {
      username: this.username,
      password: this.password,
    });

    // Mqtt error calback
    this.mqttClient.on("error", (err) => {
      console.log(err);
      this.mqttClient.end();
    });

    // Connection callback
    this.mqttClient.on("connect", () => {
      console.log(`mqtt client connected`);
    });

    // mqtt subscriptions
    this.mqttClient.subscribe("value", { qos: 0 });

    // When a message arrives, console.log it
    this.mqttClient.on("message", function (topic, message) {
      console.log(message.toString());
    });

    this.mqttClient.on("close", () => {
      console.log(`mqtt client disconnected`);
    });
  }

  // Sends a mqtt message to topic: mytopic
  sendMessage(message) {
    this.mqttClient.publish("value", message);
  }
}

module.exports = MqttHandler;

When simulator sending the data to the /simulator/data route, I am getting the value and sending the broker with value topic. I share the post request code and output of simulator below.

var mqttHandler = require("../mqtthandler");

module.exports = function (app) {
  app.get("/simulator", function (req, res) {
    res.render("iot/simulator");
  });

  // route to display all the data that is generated
  app.get("/simulator/data", require("./controllers/data").all);

  var mqttClient = new mqttHandler();
  mqttClient.connect();

  // route to write data to the database
  app.post(
    "/simulator/data",
    require("./controllers/data").write,
    (req, res) => {
      mqttClient.sendMessage(req.body.value);
      res.status(200).send("Message sent to mqtt");
    }
  );

  // delete the data when the stream is stopped or when the app is closed
  app.get("/simulator/data/delete", require("./controllers/data").delete);
};

When I send get request to /simulator/data I am able to see generated data, however this data is not being sent to broker.

//This is output of simulator

    [
        {
            "_id": "5ecfadc13cb66f10e4d9d39b",
            "value": "1.886768240197795",
            "__v": 0,
            "categories": []
        },
        {
            "_id": "5ecfadc23cb66f10e4d9d39c",
            "value": "7.351404601932272",
            "__v": 0,
            "categories": []
        }
    ]

PS: Broker is created via node-red

I would like to pass this data to broker and see the result with MQTT subscription. However I can not find where am I making mistake.

hardillb
  • 54,545
  • 11
  • 67
  • 105
Alperzkn
  • 467
  • 2
  • 10
  • 25

2 Answers2

0

Your solution is to fix your development process. Rather than working from failure debugging 2 subsystems (your publisher / simulator and your subscriber), work from success:

1) use publishers that you KNOW work, eg. mosquitto_pub, any simulator that works, etc.

2) use subscribers that you KNOW work, eg. mosquitto_sub

This will solve your problem in minutes, rather than hours or days, and let you focus on the code that you REALLY want to develop.

Gambit Support
  • 1,432
  • 1
  • 7
  • 17
-2

So a couple of things to look at here.

  1. Your this.mqttClient.subscribe() call is inline with your connect(), on.("error",...), on.("message",...) etc. So the subscribe() could fire before the connect() has finished...and thus you will never subscribe. Put the subscribe() inside the connect() block.

  2. You are subscribing to "value", which is not a proper MQTT topic. If you must, use value/# for the subscribe(), and "value/.." for the publish(). Your class only allows for the single, hard-coded topic, so won't be very useful when you want to reuse that class for other projects. Take the time now to pass the topic string to the class as well.

JD Allen
  • 799
  • 5
  • 12
  • `value` is a perfectly valid topic name, there is no need for topics to be multi level, point 2 is just wrong. – hardillb May 28 '20 at 13:31
  • Matter of opinion I guess. https://www.hivemq.com/blog/mqtt-essentials-part-5-mqtt-topics-best-practices/ – JD Allen May 28 '20 at 16:08
  • Nope, nothing in that article supports your case. A topic with a trailing slash is as bad as one with a leading slash – hardillb May 28 '20 at 16:10
  • I don't think your suggested solution is the right solution for my problem. I am able to publish via node-red to the broker and I am able to subscribe to the topic as well. – Alperzkn May 28 '20 at 18:14