SleepHelper library (preliminary)

Thank you all for your help and support - especially you @rickkas7

Here is the progress I have made with this next release (v0.09):

  • I got rid of the individual web hooks, I now use the sleepHelper publish without modification and then use a static webhook structure (more on this below) to send to Ubidots.
  • I have implemented persistent storage and validated it works. I was not able to use the murmur3_32 hashing with the two storage objects but I have validated the functionality of the hash function I have put together.
  • The device now reliably operates in both “enable sleep” and “disabled sleep” modes using the Particle function and the user button to move between them (more on this also).
  • I have updated all the #includes, header information and implemented better logging for troubleshooting.

So, here are a couple areas I would appreciate any help advice:

  1. This library allows you to specify how often data points will be collected and how often the device will connect to the Particle cloud and send its data off in the sleepHelper webhook. With some help from Ubidots (thank you David!) I was able to build a custom JSON webhook that would take the unmodified sleepHelper JSON and reformat it for Ubidots using their bulk upload API.
// Here is the JSON from sleepHelper:
{
  "soc": 96,
  "ttc": 12959,
  "rr": 20,
  "eh": [
    {
      "t": 1656265440,
      "bs": 4,
      "c": 22.9304
    },
    {
      "t": 1656265560,
      "bs": 4,
      "c": 23.3333
    },
    {
      "t": 1656265680,
      "bs": 4,
      "c": 22.9304
    },
    {
      "t": 1656265800,
      "bs": 4,
      "c": 23.4139
    }
  ]
}

// And here is the JSON in the Particle Webhook that sends the data to Ubidots
[
  {
    "device": "{{{PARTICLE_DEVICE_ID}}}",
    "values": [
      {
        "battery": "{{{soc}}}",
        "temp": "{{{eh.0.c}}}",
        "connecttime": "{{{ttc}}}",
        "timestamp": "{{{eh.0.t}}}000"
      },
      {
        "battery": "{{{soc}}}",
        "temp": "{{{eh.1.c}}}",
        "connecttime": "{{{ttc}}}",
        "timestamp": "{{{eh.1.t}}}000"
      },
      {
        "battery": "{{{soc}}}",
        "temp": "{{{eh.2.c}}}",
        "connecttime": "{{{ttc}}}",
        "timestamp": "{{{eh.2.t}}}000"
      },
      {
        "battery": "{{{soc}}}",
        "temp": "{{{eh.3.c}}}",
        "connecttime": "{{{ttc}}}",
        "timestamp": "{{{eh.3.t}}}000"
      }
    ]
  }
]

This works well but it has an obvious problem - the webhook is specific to the number of data points collected between uploads to Particle. In looking at @rickkas7 's Intermediate Webhook tutorial, it seems that it may be possible to build the webhook so it can accommodate as many data points as needed.

However, I have not been able to get this to work. Also, what if we want to include other payloads beyond data points - such as alerts or status messages? Any advice would be appreciated!

  1. I am struggling a bit with managing the sleep wake cycles of this device. Here is what I am trying to do:
  • A new device, put into service will connect to Particle and stay on-line (for configuration).
  • Once configured using the Particle console, a Particle function call will enable sleep.
  • The device will stay in this mode - normal operations - but will delay going back to sleep for 90 seconds when it connects in case I would need to remotely disable sleep for configuration / testing.
  • If physical access is possible, pressing the user button will wake the device and force it to connect.

I have the first two of these attributes working now but would appreciate any advice on how to handle the last two. Here is what I have now in the sleep_helper_config.cpp file:

        .withSleepConfigurationFunction([](SystemSleepConfiguration &sleepConfig, SleepHelper::SleepConfigurationParameters &params) {
            // Add a GPIO wake on button press
            sleepConfig.gpio(BUTTON_PIN, CHANGE);   // My debounce time constant prevents detecting FALLING
            delay(2000);                            // This is a debugging line - to connect to USB serial for logging
            Log.info("Woke on button press");
            if (!digitalRead(BUTTON_PIN)) {         // The BUTTON is active low - this is a button press
                sysStatus.enableSleep = false;      // Pressing the button diables sleep - at least that is the intent
                Log.info("Button press - sleep enable is %s", (sysStatus.enableSleep) ? "true" : "false");
            }
            return true;
        })
        .withSleepReadyFunction([](SleepHelper::AppCallbackState &, system_tick_t) {
            if (sysStatus.enableSleep) return false;// Boolean set by Particle.function - If sleep is enabled return false
            else return true;                       // If we need to delay sleep, return true
        })

If I press the user button repeatedly, I can get the device to disable sleep but not reliably. As for the 90 second delay. I could create a delay function but, how would I trigger it only when the device makes a Particle connection?

Thank you all for your help,

Chip

1 Like