C++ class for dynamic cron schedules in esphome

I developed an irrigation controller that suits my needs perfectly. But I don’t want to rely on external scheduling from HA or anywhere else. The controller needs to be completely independent of any other system ( well, except for electricity :grin: )

EDIT: See the latest version, packaged as an External Component: esphome-dynamic-cron

ESPHome has a built-in scheduler that includes cron functionality, however it is baked into the firmware and cannot be modified at runtime. So I created a dynamic cron scheduler class in C++ that can be dropped into any ESPHome project. The scheduler does two things: 1. Determines the next-run-time of your Sprinkler instance, 2. Triggers the run, when that point in time is crossed.

The Croncpp Scheduler for ESPHome includes basic setup instructions and will be kept updated as fixes and improvements are made.

I wrote this class specifically for the Sprinkler component, however it is easily modifiable to work with any ESPHome component. The functionality is unobtrusive and will not alter your ESPHome code.

Some of the features are:

  • Automate start times entirely within ESPhome, no home-assistant required.
  • Editable cron expressions, no re-flash (or re-boot) required.
  • Multiple cron expressions for each Schedule instance.
  • Multiple independent Schedule instances handle multiple Sprinkler instances (or whatever you want to schedule on your ESPHome device).
  • Remembers missed start times after power failure or reboot.

Here’s my irrigation UI (native ESPHome web UI) showing the essential controls for the scheduler. Notice the lines for “Cron Schedule”, “Next Run”, and “Disable Schedules”. Those are the main controls, and they are simple to integrate with your ESPHome project using switch, text, and text_sensor components.

I know there are other scheduling tools for ESPHome, but I wanted to roll my own to better familiarize myself with the inner-workings of ESPHome. I also wanted to create something that was simple, modular, and usable outside the context of my specific project. I have gained a lot of knowledge from members on this site, so I hope this project can be of use to others as well.

Credit to mariusbancila for the excellent Croncpp library for parsing cron expressions. That’s really where the heavy lifting happens. :beers:

EDIT: I have developed an External Component that is based on this class. It gives a simple ESPHome interface for creating dynamic cron schedules that can be edited/updated at run time, without needing to reflash or reboot. Check it out on github: esphome-dynamic-cron

2 Likes

This looks really interesting. Thanks!
I’m currently trying to replace several Orbit B-Hyve WiFi Hose Controllers and a B-Hyve Smart Indoor Timer with ESPHome devices. As I see it, I’ll have one ESP32 controlling two 12V solenoid hose valves. I’ll be building three of these units. Another ESP32 will control my in-ground 3-Zone irrigation system via a 4-channel 24V relay.
Is there a way to dynamically input program run durations for each valve or zone?

Very good! Question: setting a schedule is possible only through the web interface, but what if I use the screen? When setting the time, how do I do it?

@ronkmd The cron scheduling, whether using this dynamic component or the built-in ESPHome cron scheduler, only controls when a program cycle begins. The details of the cycle, including valve run durations, are controlled by the ESPHome Sprinkler component, or whatever process control component you’re using. If using the ESPHome Sprinkler controller, you can adjust all (most?) of the parameters in real time with the default UI elements and/or the http API that are presented with each sprinkler program you define.

Here’s a screenshot of my current 3-valve system, as presented by the ESPHome web UI. Hopefully it’s not too small to read, I had to shrink it to capture it with a single image. All of the controls on this UI are from the Sprinkler component or the Dynamic Cron component.
EDIT: The cron elements are the ones beginning with “Moana”. All other elements are from the ESPHome Sprinkler component.

@lordzid The schedule can be read and set via the web UI, or the web API, or by your own custom code and/or interface elements in ESPHome. I don’t think I’ve created any documentation on the later, yet, but the capability is there. For example, you can set the cron expression(s) for a schedule object using the setCrontab(std::string str) method.

id(lawn_schedule_id).setCrontab("0 0 1 * * mon,wed,fri")

If by screen you mean a video display / touch-screen connected to the ESPHome, you would call the above method as a result of some action triggered by the UI on the display. To get the current cron expression into the display, you can read it using the getCrontab() method.

id(lawn_schedule_id).getCrontab()

There are other less-direct ways to get/set the cron expression that may or may not suit your case, such as calling a method on a UI component that displays and sets the cron expression. I don’t have any examples of that, as I haven’t ventured into that realm yet. I would like to add a display to my irrigation controller, though… some day.

1 Like

Thanks! I just built one (of the 3) hose controllers today. Sourcing some of the hardware like 12v solenoid valves, tubing and clamps and hose adapters, etc. has been taking some time. I’ll follow up with more details soon.

I got the ESP32 programmed with Dynamic Cron and ESPHome Sprinkler Component. The cron is calling a script to start each valve’s program. Seems to be working pretty well so far. A few tweaks still needed:
I’d like to have Run Duration in minutes rather than seconds. Can’t seem to do it in ESPHome yaml with “unit_of_measure”. Maybe I need to do it in HA?
Might add some Status LEDs and Manual Run buttons to the enclosure.

I just received two Cheap Yellow Displays today. I’m thinking of using one to run my inground irrigation system and include controls for the hose controllers.