简体   繁体   中英

why do I get two events from particle.publish?

I am using code like this on a particle electron to report pulse counts from a flow meter on my kegerator to the particle cloud:


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();
   }
}

When I curl the event log into my terminal, I see two events for the first publish like so:


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

I don't see how this could happen. Why didn't it just report "ticks:47"? What am I missing?

UPDATE: I did some further testing and noticed that Particle.publish is returning false the first time when it is actually completing successfully. Is this a timeout issue? The time difference between these publishes is only about 200ms.

OK, This is at least a partial answer.

It appears that Particle.publish is asynchronous. It returns the promise of an answer that starts out as false only eventually becomes true when/if the action is actually completed. If I wait an indeterminate amount of time (say delay(10)) after Particle.publish and before checking the return code, the return value will indicate the actual success or failure of the publish. My code cannot work because the ticks that are counted while I wait will be deleted when I reset the meters. WITH_ACK gives me the same behavior.

I will have to modify my code such that no ticks are lost during the long running Particle.publish . I am thinking that each statusMessage should go onto a list until it is ack'ed by the server.

FINAL ANSWER:
I modified the code to close the window during which I can receive ticks that will then be wiped out when I reset the counters. I do this by capturing the ticks into an array and then resetting the tick counter (meter). I am using a library called PublishQueueAsyncRK (cudos to rickkas7 This library is great!) so I can just fire it and forget it. Check it out on 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();
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM