首页 > 解决方案 > 为什么我会从particle.publish 获得两个事件?

问题描述

我在粒子电子上使用这样的代码来报告从我的 kegerator 上的流量计到粒子云的脉冲计数:


void meterInterrupt(void) {
   detachInterrupt(pin);
   ticks++;
   cloudPending = 1;
   attachInterrupt(pin, meterInterrupt, FALLING);
}

void publishStatus() {
   if (!cloudPending) {
     return;
   }
   cloudPending = 0;

   getStatus(&statusMessage);
   // status message contains number of ticks since last publish

   bool published = Particle.publish("Ticks", statusMessage, PRIVATE);
   if (published) {
      resetMeters();
      lastPublish = millis();
   }
}

void loop() {
   if ((millis() - lastPublish) >= 1000) {
       publishStatus();
   }
}

当我将事件日志卷曲到终端时,我看到第一次发布的两个事件如下所示:


event: Ticks
data: {"data":"ticks:1","ttl":60,"published_at":"2018-07-03T22:35:01.008Z","coreid":"420052000351353337353037"}

event: hook-sent/Ticks
data: {"data":"","ttl":60,"published_at":"2018-07-03T22:35:01.130Z","coreid":"particle-internal"}

event: Ticks
data: {"data":"ticks:46","ttl":60,"published_at":"2018-07-03T22:35:01.193Z","coreid":"420052000351353337353037"}

event: hook-sent/Ticks
data: {"data":"","ttl":60,"published_at":"2018-07-03T22:35:01.303Z","coreid":"particle-internal"}

我不明白这怎么会发生。为什么它不只报告“ticks:47”?我错过了什么?

更新:我做了一些进一步的测试,并注意到 Particle.publish 在实际成功完成时第一次返回 false 。这是超时问题吗?这些发布之间的时间差只有大约 200 毫秒。

标签: eventscloudpublishparticle.io

解决方案


好的,这至少是部分答案。

看来 Particle.publish 是异步的。它返回一个答案的承诺,最初是假的,只有当/如果动作实际完成时最终才变为真。如果我在 Particle.publish 之后和检查返回码之前等待了一段不确定的时间(比如 delay(10)),则返回值将指示发布的实际成功或失败。我的代码无法工作,因为在我重置仪表时,我等待时计算的滴答声将被删除。WITH_ACK 给了我同样的行为。

我将不得不修改我的代码,以便在长时间运行 Particle.publish 期间不会丢失任何记号。我在想每个 statusMessage 应该进入一个列表,直到它被服务器确认。

最终答案:
我修改了代码以关闭窗口,在此期间我可以接收刻度,然后在我重置计数器时将其清除。我通过将刻度捕获到一个数组中然后重置刻度计数器(仪表)来做到这一点。我正在使用一个名为 PublishQueueAsyncRK 的库(感谢 rickkas7 这个库很棒!)所以我可以解雇它并忘记它。在 github 上查看。


void publishStatus() {
  unsigned int counters[NUM_METERS];
  unsigned int pending;

  for (int i = 0; i < NUM_METERS; i++) {
    meter_t *meter = &meters[i];
    counters[i] = meter->ticks;
    pending += counters[i];
    resetMeter(i);
  }
  if (pending) {
    String statusReport;
    for (int i = 0; i < NUM_METERS; i++) {
      statusReport.concat(String::format("%i:%u|", i+1, counters[i]));
    }
    publishReport(statusReport);

    lastPublished = millis();
  }
}

void publishReport(String report) {
  if (report != "") {
    publishQueue.publish("PourLittleTicks", report, PRIVATE);
  }
}

void loop() {
  if ((millis() - lastPublished) >= PUBLISH_INTERVAL) {
    publishStatus();
  }
}

推荐阅读