使用MQTT进行基本本地异步

时间:2019-03-29 17:21:38

标签: node.js mqtt

我需要将基本客户端和本地客户端与MQTT同步。如果客户发布,则另一方将收到消息。

  • 如果我的MQTT代理关闭,则需要停止发送消息,将消息保存在某个地方,等待连接,然后继续发送。

  • 如果我的本地或基本客户端关闭一秒钟,我需要保存未发送的消息,然后在打开我的基本/本地客户端时发送它。

我正在使用Node.js,无法弄清楚如何实现。

这是我与MQTT服务器连接或断开连接时的处理程序。

    client.on('connect',()=>{
      store.state = true;
      run(store).then((value)=>console.log('stop run'));
    });

    client.on('offline',()=>{
      store.state = false;
      console.log('offline');
    });

这是我的run函数。我使用store.state决定是否应该停止此间隔。但是这段代码似乎并不是实现我的概念的好方法。

function run(store) {
  return new Promise((resolve,reject)=>{
    let interval = setInterval(()=>{
      if (!store.state) {
        clearInterval(interval);
        resolve(true);
      }
      else if (store.queue.length > 0) {
        let data = store.queue.pop();
        let res = client.publish('push',JSON.stringify(data),{qos:2});
      }
    },300)
  });
}

我应该怎么做才能实现始终发送,在“断开连接”时停止,然后在连接后继续发送的功能?

1 个答案:

答案 0 :(得分:0)

  

我认为设置300ms间隔不是很好。

如果您希望某些东西“总是运行”,则应按设置的时间间隔并且尽管循环内有任何错误,但setInterval()是有意义的。没错,可以比“每300毫秒一次”清除更快的邮件。

MQTT.js has a built-in queue起,您可以通过使用它进行很多简化。但是,您的消息将发布到称为“推送”的目标,因此我想您希望它们按照队列的顺序进行传递。这个答案排在队列中,着重于在确认最后一条消息后立即发送下一条消息。

  

如果res = client.publish(..)为false怎么办?

好点!如果要确保它到达,最好在发布成功后将其删除。为此,您需要检索值而不删除它,并使用callback参数找出发生了什么(publish()是异步的)。如果那是唯一的更改,则可能看起来像这样:

let data = store.queue[store.queue.length - 1];
client.publish('push', JSON.stringify(data), {qos:2}, (err) => {
  if(!err) {
    store.queue.pop();
  }
  // Ready for next publish; call this function again
});

扩展它以包括基于回调的运行:

function publishFromQueue(data) {
  return new Promise((resolve,reject)=>{
    let res = client.publish('push', JSON.stringify(data), {qos:2}, (err) => {
      resolve(!err);
    });
  });
}

async function run(store) {
  while (store.queue.length > 0 && store.state) {
    let data = store.queue[store.queue.length - 1];
    let res = await publishFromQueue(data);
    if(res) {
      store.queue.pop();
    }
  }
}

这应该尽快传递所有排队的消息,而不会阻塞。唯一的缺点是它不能持续运行。您有两种选择:

  1. 按照已设置的时间间隔重复执行。速度较慢,尽管您可以设置更短的间隔。
  2. 仅在需要时run(),例如:
let isRunning = false; //Global for tracking state of running

function queueMessage(data) {
  store.queue.push(data);
  if(!isRunning) {
    isRunning = true;
    run(store);
  }
  isRunning = false;
}

只要您可以使用它而不是将其推送到队列,它的长度就应该相近,并且更加直接和有效。