Javascript 如何将消息从mosca代理发送到mqtt.js客户端

Javascript 如何将消息从mosca代理发送到mqtt.js客户端,javascript,mqtt,iot,Javascript,Mqtt,Iot,我们设置了一个由供电的MQTT客户机(在台式PC上或在实际板上,两者相同)和一个由供电的MQTT代理,这一个运行在台式PC上 我们能够成功地将带有特定主题的消息从客户端发送到代理,但现在我们却陷入了相反的境地:将消息从代理发送到客户端 我们正在遵循两个项目文档中提供的代码示例,但运气不佳。客户端能够正确注册到主题,但在发送消息时不会做出任何反应。代理能够正确地发送消息,也能够侦听自己的消息,因为它正在侦听所有消息 摘自MQTT broker: broker.on('published', fun

我们设置了一个由供电的MQTT客户机(在台式PC上或在实际板上,两者相同)和一个由供电的MQTT代理,这一个运行在台式PC上

我们能够成功地将带有特定主题的消息从客户端发送到代理,但现在我们却陷入了相反的境地:将消息从代理发送到客户端

我们正在遵循两个项目文档中提供的代码示例,但运气不佳。客户端能够正确注册到主题,但在发送消息时不会做出任何反应。代理能够正确地发送消息,也能够侦听自己的消息,因为它正在侦听所有消息

摘自MQTT broker:

broker.on('published', function(packet, client) {
  console.log('MQTT broker received message');  // it passes by here
  console.log(' - packet:', packet);
  console.log(' - packet payload:', packet.payload.toString());
});

// ...

var packet = {
  topic: 'our_custom_topic',
  payload: ourCustomPayload,
  qos: 1,
  retain: false,  
};

console.log('MQTT broker sending message to client ...');

broker.publish(packet, function() {
  console.log('Message sent');  // it passes by here
});
摘自MQTT客户机:

client.on('connect', function () {
  console.log('MQTT client connected');

  client.subscribe('our_custom_topic', { qos: 1 }, function onSubscribe(err, granted) {
    if (err) {
      console.log('subscribe errors:', err);  // no error shown
    }

    if (granted) {
      console.log('subscribe granted:', granted);  // it passes by here
    }
  });
});

// ...

client.on('message', function (topic, message, packet) {
  console.log('MQTT client received message');  // it DOESN'T pass by here
  console.log(' - topic', topic);
  console.log(' - message', JSON.stringify(message));
  console.log(' - packet', JSON.stringify(packet));
});
更新 当持久性基于mongoDb时,问题似乎就出现了。相反,当持久性基于内存时,消息会正确地发送给订阅者。以下是我们在依赖mongoDb持久性时的发布订阅设置。实际上,它是一个运行在mongolab.com上的开发实例:

var mongoDbSettings = {
  // remote MongoLab mongodb instance
  url: 'mongodb://mqtt-db-user:<OUR-USER-CODE>@<THEIR-INSTANCE-SUBDOMAIN>.mongolab.com:39291/sample-mqtt-datastore',
  pubsubCollection: 'myCollections',
};

var mongoDbBrokerSettings = {
  port: 1883,  // mosca (mqtt) port

  // using ascoltatore over MongoDB
  backend: {
    type: 'mongo',
    url: mongoDbSettings.url,
    pubsubCollection: mongoDbSettings.pubsubCollection,
    mongo: {},
  },
  persistence: {
    factory: mosca.persistence.Mongo,
    url: mongoDbSettings.url,
  }
};

var broker = new mosca.Server(mongoDbBrokerSettings, function onCreated(err, broker) {
  // assume no errors

  console.log('MQTT broker is up and running');
});
var mongoDbSettings={
//远程mongodb mongodb实例
网址:'mongodb://mqtt-db-user:@.mongolab.com:39291/sample mqtt datastore',
pubsubCollection:“myCollections”,
};
var mongoDbBrokerSettings={
端口:1883,//mosca(mqtt)端口
//在MongoDB上使用ascoltatore
后端:{
键入:“mongo”,
url:mongoDbSettings.url,
pubsubCollection:mongoDbSettings.pubsubCollection,
蒙戈:{},
},
持久性:{
工厂:mosca.persistence.Mongo,
url:mongoDbSettings.url,
}
};
var broker=new mosca.Server(mongoDbBrokerSettings,函数onCreated(err,broker){
//假设没有错误
log(“MQTT代理已启动并正在运行”);
});

有人发现这有什么问题吗?

MQTT代理处理客户机之间的消息,但不发送它们(最后遗嘱特殊消息除外)

您必须实现以下功能:

  • 客户端A订阅一个主题:test/one
  • 客户端B将消息发布到同一主题:test/one
  • 自动订阅此主题的所有客户端(如客户端A)都将收到消息
但在Mosca中,您可以实例化充当MQTT客户机并可以发布的客户机对象

您应该调试此消息是否通过订阅
我们的自定义\u主题
的外部客户端(如mosquito\u sub或MQTT.fx)有效发布


持久性不应影响消息的发布,但您可以安装MOSQUITO并测试是否将其用作后端工程

您可以直接从代理发布,因为它是Mosca公共API的一部分:

/**
 * Publishes a packet on the MQTT broker.
 *
 * @api public
 * @param {Object} packet The MQTT packet, it should include the
 *                        topic, payload, qos, and retain keys.
 * @param {Object} client The client object (internal)
 * @param {Function} callback The callback
 */
Server.prototype.publish = function publish(packet, client, callback)...

只要您的客户机已订阅,您就可以通过
broker.publish({topic:/foo/bar,payload:'foo'},client)
在您要发送的模型实例的客户机上(即通过回调)发送。

我们修补了一些调试日志,显然它的
\u handlePublish
方法甚至没有被调用,因此,实际上无法触发任何
'message'
事件。仍在调查…在client.js链上,当代理发送消息时,甚至没有调用
进程中的
\u handlePacket
方法。查看mosca端,我们向添加了一些调试日志,可以看到调用了
发布
方法,以及.published
回调的内部
方法,在某个时刻,我们看到了某种异常或错误消息,导致客户端自行断开连接并重新连接,但在服务器端没有报告任何问题。Error was参数必须是
publish
中的字符串,位于
…\mqtt connection\node\u modules\mqtt packet\generate.js:227:22
我们提供了一个示例测试,其中一个服务器发布了一个主题,一个客户端订阅了该主题:除了服务器创建的回调调用了两次之外,该方法有效。在实际项目中,MQTT代理也是一个express+socket.io web服务器,当然位于不同的端口上。不知道这是否是问题的根本原因谢谢你的反馈。是的,这是一种“经典的”——可以这么说——工作方式,但API似乎也支持服务器发送消息,我们没有发现任何不应该这样做的提及。在我们的上下文中,该场景非常有用。MQTT.js只是node.js的MQTT客户机实现。您需要为node.js运行类似mosca的代理吗?我认为这实际上就是我在开始时描述的场景:一个由MQTT.js支持的MQTT客户机,一个由mosca支持的MQTT代理,每个代理都运行在node.jsBrokers上处理消息。客户端通过连接到代理并订阅主题来获取消息,或者通过连接到代理并发布到主题来发送消息。代理无法发送消息,客户端连接到代理,是。“代理无法发送消息,客户端连接到代理,是。”在mosca API或文档中,这在哪里被阻止?我知道常规行为,但正如我所说的,在代理实现中似乎没有什么不符合的,即代理可以发送消息。如果您查看问题和代码示例,这实际上就是我们试图做的。它适用于基于内存的持久性,而不适用于基于mongodb的持久性(mongodb运行在mongolab.com上),您的意思是存储和访问客户机对象吗?上述解决方案不应该使用mqtt配置的后端。该值应相对于用户或设备或您的模型名进行存储。对不起,我的错,我不明白。我们的客户订阅了我们的自定义主题
。Broker准备一个包含该主题的数据包并发布它。客户机应该接收并对其作出反应,但它的行为表现为什么都没有发生。如果服务器配置了内存内持久性,则相同的代码位(服务器和客户机)保持不变,如果服务器配置了mongodb持久性,则停止工作。由于其他原因,需要进行持久性配置(例如guar