Coming in cron-plus v3: a "Cron Filter" node with natural language conditions

I'm working on v3 of node-red-contrib-cron-plus and before I get too far down the road I'd like some opinions on the headline feature.

v3 itself brings a swap of the underlying solar library (which is why it's a major version, computed solar event times shift by a few seconds (more accurate)) and includes lunar rise/set features. But the thing I want feedback on is a second node being added to the package: Cron Filter (see item 4 at the end).

What it does

It sits after a cronplus node (or TBF, any node you desire) and allows or blocks messages based on a time based condition. Output 1 is for "allowed" messages, output 2 is "blocked" messages (so you can set a sensible text condition and the 2nd output is the natural negation - also useful for logging!). So you can run a schedule every 5 minutes and only let messages through "when the moon is visible", or "on weekends or after sunset", or "between 15 and 30 minutes past the hour". Things cron syntax can't say, or can't say without mucho pain.

The interesting part is how you enter the condition.
There are no dropdowns.
You type what you mean:

Gif showing condition parsing

As you type, a line under the field shows exactly how your words were understood. If it can't make sense of the input it says so and suggests examples. This is a plain parser, by the way. No AI, no cloud, nothing leaves your machine. It's a tokeniser / grammar parser, so the same text always parses the same way, offline.

Why free text instead of form fields

I did sketch the "proper" UI first. Day of week checkboxes, week of month selectors, month pickers, year ranges, sun elevation min/max, moon phase dropdowns, and/or/not group builders... it turned into a wall of widgets before it covered half the cases. Every condition type multiplied the dialog. And honestly, nobody (well me) wants to click through 10 fields to say "weekdays between 9am and 5pm".

Free text turned out to be easier from both ends. Easier to build (and maintain ) than that form & quicker for users, because you already know how to say what you want.

Examples

These are real inputs and the actual "understanding" text the editor shows for each:

You type It understands
on saturdays only day is Saturday
weekdays between 9am and 5pm day is a weekday (Monday to Friday) and time is between 09:00 and 17:00
1st day of the month day of the month is 1
3rd tuesday of the month day is the third Tuesday of the month
last month of the year month is December
christmas eve date is 24 December (christmas eve)
quarter past five time is 05:15
ten past the minute is 10 past the hour (every hour)
is night it is night (sun below -18 degrees)
2 hours after sunset more than 2 hours after sunset
sun above 30 degrees sun altitude is above 30 degrees
moon is high the moon is high (above 45 degrees)
moon is 90% illuminated the moon is at least 90% illuminated
on weekends or after sunset day is a weekend, or after sunset
(last day of the month or wednesday) and after 10pm (day is the last day of the month, or day is Wednesday) and time is after 22:00
odd months the month number is odd
even days in janury the day of the month is even and month is January - assumed 'january' for 'janury'
weekends after 10pm when the moon is visible day is a weekend and time is after 22:00 and the moon is above the horizon (visible)

Conditions combine with and, or, not, except and brackets. Without brackets, and binds tighter than or, and the understanding line always shows the grouping it settled on, so mixed conditions are never a silent surprise. Minor typos get corrected ("saterday" works, with a note saying what was assumed).

Knowing what will happen before you deploy

Next to the understanding line there's a "details & upcoming matches" popout. It breaks the condition down (days, dates, months, years, times, sun, moon) and previews the next few periods when messages would actually pass, computed for your location and timezone:

Once deployed, the node status shows the current decision and when it will next change:

The practical bits

  • Sun and moon conditions need a location. The node takes it from the incoming message (msg.location, or the schedule location a cronplus solar/lunar event already carries), or from a fixed/env setting on the node with the same map picker as cronplus.
  • Messages are judged by their own timestamp when they carry one (msg.ts or the cronplus trigger time), otherwise by arrival time. Handy for testing: inject a message with a Tuesday timestamp and watch it route.
  • The condition itself can come from a fixed string, an env var, or a message property, so different messages can carry different conditions.
  • Output message adds msg.filter with the decision (the parsed description and a per clause explanation of why).

What do you all think :thinking:

  1. Does the natural language input feel right or would you rather have had the form fields after all? (ps, I am unlikely to waver here, but asking to get feelskis)
  2. What phrases would you expect to work that might not?
    • some examples of what you would hope to enter (and be understood) would be great!
    • nothing too wacky and must be time/date/solar/lunar relevant!
  3. A couple of judgement calls I made (argue with me): "the sabbath" means Saturday, "last day of the week" means Sunday (weeks start Monday, ISO style), and "moon is 90% illuminated" reads as at least 90%. Each is spelled out in the understanding line so nothing is hidden, but the defaults are debatable.
  4. The name of the node: "Cron Filter". Yeah, I hate it too! Any thoughts? "Time Gate", "Time Filter", "Temporal Switch", "cron router" other?

Absolutely. I look forward to trying it!

If I were to specify "at 7am", would a message arriving at 07:00:30 be passed?

Does "7am" mean UT, the local time of the browser or the local time of the server?

Can you cope with "sunset in a month with two full moons"?

I looked up Sabbath and even if you only consider one religious tradition it seems pretty fluid.

Perhaps religious date/times like Sabbath, Ramadan & Easter are better left to specialised apps?

Time Gate.

Cool!

Yes. It is minute resolution. I have also debated allowing a specific time seconds accuracy (e.g. "at 07:00:30") but for now, it is deliberately a whole minute (it is spelled out in the built in docs too)

The node's Timezone setting. When blank, the server's system timezone (never the browser) That's the only sane answer for a server side filter, and it matches cronplus's existing convention.

Thanks - a decent stress test (grrrr)! The short answer is "no". That's a quantifier over a set ("does this month contain two X events?"), not a property of the message's instant (i.e. a different class of machine from the term evaluator ive wrote). The parser's failure mode however will tell you "did not understand" rather than silently guessing so there is a safety net. Also, the specific case you are describing is a blue moon and "blue moon" (second full moon in a calendar month) is actually computable as an instant property - so I'm gonna add it. That should allow things like "blue moon and within 30 minutes of sunset" and "blue moon and moon is high and after 10pm" and "blue moon at the weekend"

"Time Gate" sounds like a B-Movie :slight_smile:

An "In" function maybe?

Month in[Jan, Jul, Oct]

It does :thinking:

But we are used to Simple Gate and Queue Gate nodes with similar pass/block function.

Alredy parses as you'd expect
image

however not phrasing i would use (so not shown as green summary but as a warning yellowy colour)

If however you said any of the following it would parse cleanly:

image
image
image

CRON Filter seems good enough to me. :smiley: Does what it says on the tin.

Also good.

I like the idea. I've had to patch together a lot of what this would do. Too bad the name flux capacitor is taken. How about something like
Steve's node in code keeping everything really simple, or Snickers,

Good addition to cron-plus.
I'd like to mention the excellent work of @jens_rossbach with node-red-contrib-chronos (node) - Node-RED that already includes a time filter node (Time Filter Node · jensrossbach/node-red-contrib-chronos Wiki · GitHub) among other useful time/date related nodes.
Could be an inspiration or someone to work with in order to provide the best of both worlds and avoid too much duplication of efforts !!

Great idea. Look forward to seeing it live.

  1. Does the natural language input feel right

Always yes. I have done this myself for a project and it's awesome to use

  1. What phrases would you expect to work that might not?

...after 10pm.
At what point does it start and stop? Would it be until the day resets at 0:00?

  1. "the sabbath" means Saturday, "last day of the week" means Sunday

"Last day of the week" changes for each country. I would not allow those, or specifically specify that you are using the ISO standard

  1. The name of the node

Time Cop? :slight_smile:
Cron Filter is fine.

Yes. (0 is less than 22 :wink: ) but you can be explicit too:

image

The understanding line calls this out as does the status

image
image

  1. Does the natural language input feel right
    Absolutely

  2. What phrases would you expect to work that might not?
    Current hour... from right now to the end of the current hour. Is this possible ?
    Or will it be restarted at the beginning of the next hour...and so on ...

  3. ‘The Sabbath’… if you start with that… then why not ‘the King’s birthday’ ? It gets a bit tricky, doesn’t it?

  4. The name of the node
    Cron Filter is fine, why not Cron Spec ?

Not sure how this could work TBH. Likely doesn't make sense for a statically configured node. I'll think on it!

Not the first to mention this. I heard that term many moons ago and was cemented in my head by the Black variation :wink: Sabeth is no longer mentioned or covered in the node.

Thanks for the positive feedback BTW.

Not sure if this is for the main node or the filter node but one of the timing issues I get all the time is for lighting that is partly based on sun position but with fixed time constraints or where I need a sun position variation depending on time of year (due to angles/shadows changing the indoor ambient lighting).

e.g.

  1. I want a light turned ON at 7am UNLESS it is already past sunrise+1hr
  2. I want a light turned OFF at 8:30am UNLESS it is still before sunrise+1hr
  3. I want a light turned ON at sunset-1hr EXCEPT in March and April (due to house and sun positions)
  4. I want a light turned ON at sunset-2hr EXCEPT between June and September when it should be sunset-1hr

I've ended up either just not bothering to adjust things or having crazy complex flows that I'm sure can be done better but I just can't quite get my head around them.

Might that be better done using the height of the sun above the horizon?

My weather station has a light meter so I am in the lucky situation of being able to use the ambient light level for that sort of thing.

I want a light turned ON at 7am UNLESS it is already past sunrise+1hr

Keep the 7am schedule as is. Wire it into a Cron Filter node with condition not 1 hour after sunrise. Once sunrise+1hr has passed for the day, the filter blocks the 7am message instead of the light turning on unnecessarily

I want a light turned OFF at 8:30am UNLESS it is still before sunrise+1hr

Same pattern, flipped. Keep 8:30am in cron, filter with 1 hour after sunrise. While it's still before sunrise+1hr the filter blocks the off command. once sunrise+1hr has passed, it lets it through.

I want a light turned ON at sunset-1hr EXCEPT in March and April (due to house and sun positions)

Change the schedule itself to a solar event, sunset with a -60 minute offset, so it fires at the right clock time every day without any math. Filter it with except march and april.

want a light turned ON at sunset-2hr EXCEPT between June and September when it should be sunset-1hr

A filter only blocks or lets through, it can't shift when something fires, so this one needs two schedules feeding the same light. A solar schedule at sunset-2hr filtered with not june to september, and a second at sunset-1hr filtered through a june to september. There are other approaches (the cron filter has 2 outputs so you could use the 2nd output (denied) and the topic to redirect.

image

Firstly, this Node looks good and I, for one, can see multiple uses! Secondly, we can all argue for our own personal wishes/preferences, so here goes...

My week starts on a Sunday, as I was taught in school more than 'just a few years ago'. But then I am probably in the minority and Heaven Forbid if I go against ISO Standards. (said Tongue in Cheek!) (Tickbox for Start of Week?)

I use Civil Dawn and Civil Dusk with time corrections similar to Julian's observations "Civil Dawn + 1 Hr"

Cron Filter is good, but might just unconsciously tie it to Cron/Cron Plus, so Time Gate might be the better name using the Simple and Queue Gate argument.

Keep up the good work @Steve-Mcl