Почему я получаю два события из частицы.

Я использую такой код на электроне частиц, чтобы сообщать о числе импульсов от расходомера на моем кегераторе к облаку частиц:


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"}

Я не понимаю, как это могло произойти. Почему он просто не сообщил "тики:47"? Что мне не хватает?

ОБНОВЛЕНИЕ: Я провел дополнительное тестирование и заметил, что Particle.publish возвращает false в первый раз, когда он действительно успешно завершается. Это проблема тайм-аута? Разница во времени между этими публикациями составляет всего около 200 мс.

1 ответ

ОК, это хотя бы частичный ответ.

Похоже, что Particle.publish является асинхронным. Он возвращает обещание ответа, который начинается как ложный, только в конце концов становится истинным, когда / если действие фактически завершено. Если я подожду неопределенное количество времени (скажем, задержка (10)) после Particle.publish и перед проверкой кода возврата, значение возврата будет указывать на фактический успех или неудачу публикации. Мой код не может работать, потому что тики, которые считаются во время ожидания, будут удалены при сбросе счетчиков. 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();
  }
}
Другие вопросы по тегам