Software updates for sleeping devices

I have a project that uses photon nodes collecting environmental data running on batteries. Because the nodes run on batteries, the nodes use ‘SLEEP_MODE_DEEP’ to save the batteries. My problem was (is) that I needed a way to take the nodes out of deep sleep mode remotely so that firmware upgrades could be done OTA. I devised a way, using control software running on a ‘master’ node.

The master node has a ‘modeflag’ variable that can be changed with a function call from the CLI. That is the easy part, the rest gets a little complicated.

The battery nodes also have a ‘modeflag’ variable that controls if the node uses deep sleep. The trick is to get the new mode change from the master node to the proper battery node. Each battery node has a unique ID number. Here’s where we play ping pong.

When a battery node wakes up and comes online, it publishes an event that tells its mode (Sleep or Looping),
if the mode doesn’t match the mode that the master has, then the master publishes a ‘changeMode’ event that all the battery nodes subscribe to. If the ‘changeMode’ value matches the battery nodes ID then it’s ‘modeflag’ is changed to move that node from ‘Sleep’ to ‘Loop’ mode. Now allowing OTA updates.

The problem with all this is time, the battery node has to stay up for a least 10 seconds for all the event handshaking to complete. This is to long for battery operation! Without this overhead the nodes can complete a data transfer and be back asleep in about 2 seconds.

What seems to me would be a better solution would be to have a ‘cloud’ variable that each battery node could check when it awakes, saving all the back and forth handshaking (and time).

Also, while I’m on the subject of things I would like. The log page shows all the activity for all my photons, I only have a few, but with many nodes this gets cluttered. A way to filter this display to only the devices I am working on would be a big help.

1 Like

With the opening a free tier for the Particle Console for products with less than 25 devices you now can have pending firmware updates without extra code or publish/subscribe workarounds.

2 Likes

I have bee using the new Console, but how do you do ‘pending updates’?

You create a product, get a product ID, set that product ID in your code, add a device ID to your product list, upload a product binary and next time that device gets online it should receive the binary.

That’s just a quick recap of the docs
https://docs.particle.io/guide/tools-and-features/console/#configuring-your-product

Thanks, Since I never considered my project a ‘Product’, I never thought about looking there!

Well I made my device a product, compiled a new version, released it, device came online, NO UPDATE!

This a lot of hoops to jump through, when all I want to do is develop software on a configured device (as in the real hardware) and debug it. I understand the need to deploy to many devices, but I just want to deploy to one device that wakes up every so often (by design) and change my firmware. This is a device in a sealed case out in the real world and I need to develop in the real world. Even using the existing tools I can’t get the device to update. The device comes online for about 2 seconds to send data and go back to sleep (battery!). If this is not enough time, then it defeats the whole purpose of DEEP_SLEEP.

I don’t think that only 2 seconds of awake / online time is long enough. Maybe if you increase the awake time, your device will be able to find and download the update.

Increasing awake time decreases battery life. if during connection the version is checked, then the device should go into update mode, and not run the app until it completes. At least that the way it shoud work. Who knows!

Could you just try a longer wake periode e.g. once per day or once every ten wakes?
If you are still in the middle of development, you might be able to accept a bit more power consumption, just for the sake of shorter dev cycles, and once you got a stable state, having a once in a while check cycle might still be acceptable.

Since we don’t know your code I’d have to guess, but if you were using SYSTEM_THREAD(ENABLED) you must be aware of the asynchronous nature of your code and the cloud tasks. The cloud tasks might be aware of the pending update, but might not have the time to pull the breaks before you cut the connection.

4 Likes

I am having to address the same case, a battery operated device that will run briefly and go back to deep sleep.

An idea that I am considering is to pass a variable to the device during a normal update (by subscribing to a “status” service). The value of the variable will be used to increment the amount of time the unit waits before going back to deep sleep. I need to figure out few other details, including to ignore the variable if the version of software is already updated.