Alright... finally getting around to adding this additional Device OS based watchdog to my existing code base.
What I'd like to do is call Watchdog.refresh() on every successful publish (received an ACK back from the Particle cloud). This essentially would allow for a cloud side watchdog but without burning extra data operations to pet a watchdog using Particle.subscribe() or Particle.function(). I currently use the PublishQueuePosixRK library to handle queueing and publishing of events. A very nice library by the way. Digging through the .CPP of the library, it looks like there is a Private callback function that gets called with each successful publish:
void PublishQueuePosix::publishCompleteCallback(bool succeeded, const char *eventName, const char *eventData) {
publishComplete = true;
publishSuccess = succeeded;
}
@rickkas7 - What do you think of the approach outlined below. If it's a reasonable approach, would you be open to updating the PublishQueuePosix library to enable petting the device watchdog during this callback? I'd be happy to make a pull request. My initial thought is by default the value would be false. I'd simply call a function like PublishQueuePosix::ACKWatchdogRefresh(True). Might have to use an ifdef so the library would still work in earlier device OS versions? Here is what I had in mind:
In the main.cpp Setup:
Watchdog.init(WatchdogConfiguration()
.capabilities(WatchdogCap::NOTIFY | WatchdogCap::DEBUG_RUNNING | WatchdogCap::SLEEP_RUNNING)
.timeout(60min));
Watchdog.start();
// Register this callback to be called when the cloud side watchdog timer expires.
// Since we also have the AB1805 watchdog, we can just set a flag and then handle the deep power down in loop. The device itself is running fine, it's just not successfully publishing events like it should.
Watchdog.onExpired([]() {
watchdogExpiredFlag = true;
});
In the main.cpp Loop to handle the watchdog expired event:
//If the watchdog expired, then do a deep power down reset.
if (watchdogExpiredFlag == true) {
if(watchdogEnable == 1){
Log.error("Device/Cloud Side Watchdog Expired. Let's do a deep power down reset");
softDelay(100);
ab1805.deepPowerDown();
}
// If the watchdog is not enabled, then just Disconnect and turn cellular off. We don't want to reset in case the customer as an actuator on.
else{
Log.error("Device/Cloud Side Watchdog Expired but watchdog is disabled, let's disconnect from Particle and turn cellular off");
Particle.disconnect(CloudDisconnectOptions().graceful(true).timeout(8s));
softDelay(1000);
Cellular.off();
softDelay(2000);
}
}
Modify the PublishQueuePosix.cpp
void PublishQueuePosix::publishCompleteCallback(bool succeeded, const char *eventName, const char *eventData) {
publishComplete = true;
publishSuccess = succeeded;
Watchdog.refresh(); //Pet the watchdog during the publish complete callback:
}
Is this a reasonable approach?
EDIT
This approach may work on a P2 series but doesn't work as expected on a Boron/B Series due to the different behavior of watchdog. The MCU resets itself IMMEDIATLY after calling the Watchdog.onExpired interrupt.
Instead, I'll just let the device reset the MCU itself instead of the AB1805.deepPowerDown().