Creating Capabilities with Rule Templates: Time of Day

NOTE: As of OH 3.3 the Alarm Clock rule template is replaced with a native DateTime Trigger which will trigger a rule based on the state of a DateTime Item.

With the introduction of the Marketplace for rule templates I thought it might be a good time to show how one would use rule templates, not just by themselves but together to build up a fairly complex automation without needing to code anything at all, or minimal coding.

In this case we will implement a simple version of [Deprecated] Design Pattern: Time Of Day using Alarm Clock Rule and To Today.

In short, we will create a time based state machine that commands an Item at the beginning of a given time of day with the name of that time of day. This Item can then be used to drive other rules and or provide an easy way to test what time of day it is to control the behavior of automations.

The Alarm Clock Rule template create a rule that will run a given Rule based on a change in a DateTime Item’s state. The To Today rule template will create a rule to move all DateTime Items with a given tag to today’s date, keeping the time the same.

First steps

Install the Templates

In MainUI open Settings → Automation

Browse through the list from the Marketplace and install the Alarm Clock Rule and To Today templates.

Define the Items

We will have five times of day. We will use an Design Pattern: Associated Items naming scheme which will make some of the next steps easier.

State Time Item name
MORNING Based on a time published to an Item by the Android app that indicates when the next alarm set on the phone will go off. ToD_MORNING
DAY Astro binding sunrise. ToD_DAY
AFTERNOON Astro binding dusk event with a -120 minute offset. ToD_AFTERNOON
EVENING Astro binding sunset without an offset. ToD_EVENING
NIGHT 10:00 pm ToD_NIGHT
BED 11:45 pm ToD_BED

There is a mix of Items hard coded to a specific time and Items that are populated from a binding or externally. These are just examples. You must choose your own times of day and where those times of day get their date times from.

Create all of the above Items using your approach of choice. Just make sure they are DateTime Items.

There is one more Item to create, the TimeOfDay Item. This Item needs to be a String Item. In my screenshots this will be called TimeOfDay_Example.

NOTE: The rule templates assume that the DateTime Items are persisted and restored on startup. If you are running a default OH 3 instance this is already configured for you.

Configure Android App

Skip if you are not using the Android App to drive one of your Items.

In the openHAB Android app open the app settings.

Scroll down to “Send device information to server” and tap “Alarm time”.

Tap to toggle this feature to on and enter “ToD_MORNING” as the Item name.

Note, when there is no alarm scheduled the Item will be set to NULL.

Configure the Astro Binding

Skip if you are not using the Astro binding to drive one or more of your Items.

Install and configure the Astro Binding. Accept the Thing discovered from the inbox. We’ll use astro:local:sun for the Thing ID in these examples. Use your Thing ID in your Item configs.

Navigate to the Astro Thing, open the Channels tab and scroll down to the Dusk section. Select the “Start Time” channel and click on “Configure Channel”. Set the offset to -120. Link this Channel to ToD_AFTERNOON.

Scroll up to the Sunrise section of Astro Channels and link the “Start Time” Channel to ToD_DAY.

Select the “Start Time” Channel from the Sunset section of Channels and link it to “ToD_EVENING”.

Widgets to Set Hard Coded DateTime Items

Navigate to Settings in MainUI and click on “User Interfaces”. Browse though the list of Marketplace offerings to find the “DateTime Stand Alone Widget”. You may need to click on “Show All”. Install it.

If you plan on putting these Items into your model, also find and install the DateTime List Item widget.

Navigate to the DateTime Items you’ve defined that have hard coded times. In our case that’s ToD_NIGHT and ToD_BED. Under “Metadata” click “Add Metadata” . Select “Default Standalone Widget”.

For the widget field choose “rlk_datetime_standalone” from the list under “Personal Widgets”. Enter a label to identify the Item in the widget and if necessary select the Item. Save.

Optionally repeat for the “Default List Item Widget” only this time choose “rlk_datetime_list” from the list under “Personal Widgets”.

Now by default where ever this Item is shown, a nice date and time selection widget will be used. Use the widget to set the date and time for your hard coded Items. Clicking on the calendar icon of the widget will open a nice date picker widget.

Clicking the check will post that date time to the Item. The current state of the Item is shown at the bottom of the widget.

You can set the Item’s date and time from any of your pages with these widgets or from the Item’s setting page. If you semantically tag the Item, make sure to set the “Default List Item Widget” do you have the same ability on the cards shown on the Overview page.

Once the widgets are applied to an Item, go ahead and set the date time for those Items. Note that the new state may not always show up immediately under the widget when setting the state from the Item’s settings page.

Now when you look at the Items in the Items settings you should see that all of them have a non-NULL state except for MORNING if you don’t have an alarm scheduled.

No Code Solution

In this approach we will not be using any code at all, only the UI. This means no Script Conditions or Script Actions. But we will be instantiating some rules.

Create the Transition Rules

In the Rules section of MainUI click on the + icon to create a new rule.

Give it a reasonable Unique ID, name and description.

Skip down to the “Then” section and add an Action. Choose “Item Action.”

Pick the TimeOfDay Item from the list. Check “show non-semantic items” if you’ve not tagged your Items.

Leave “send a command to” selected and for the “Command to send” enter “MORNING”.

image

Click Done and Save.

Repeat for the remaining times of day Items, always choosing the TimeOfDay Item to send the command to and the name of the time of day as the command to send. See the Advanced section below for a way to make this easier.

Advanced

Now that you’ve created the one rule for MORNING, click on the “Code” tab and copy the YAML presented there to the clipboard.

Return to the Rules page and click the + icon to create a new rule. Once again enter reasonable values for the Unique ID, Name, and Description for the rule.

Now click on the “Code” tab and paste the YAML into the form, replacing what ever is there already.

Change the “command” field to the time of day this rule is for (e.g. change from “MORNING” to “DAY”).

image

Save and repeat for the rest of the times of day.

Once you are done you should have one rule for each time of day Item.

Note that there is nothing preventing you from adding anything to these rules. Instead of driving a time of day state machine, you can just code your time of day automations right here in these rules. Or this can drive some other device’s state, such as an HVAC system.

Too Many Rules!

See below for an alternative.

Instantiate Time of Day Alarm Clock Rules

We now have a rule for each time of day to transition. Now we need to instantiation a rule for each time of day that will call the transition rules at the time indicated by the DateTime Item’s state.

Since we’ve already installed the template we just need to create a new rule by clicking the +. Once again enter something reasonable for the Unique ID, Name, and Description.

This time instead of build the rule itself we will select “Schedules a timer to run a script” from the list of Templates.

Select ToD_Morning for the “Alarm Time Item” and “Time of Day Morning” as the “Script to Call”.

Save.

You will see now that the template has turned into a complete rule. You can click around to see how it’s built and look at the code if you want but you don’t have to. The rule has been tested and is known to work as is.

Click “Back” and repeat for all the other times of day.

Unfortunately there isn’t a short cut for this but I was able to set up all the rules from the template in about 8 minutes.

Last Step, To Today

We have one final step. Some of our Items are hard coded which means that every day they need to be moved to the next day to cause the Time of Day X Manager rule to trigger which will schedule the time when the Time of Day X rule will run. The rest of the Items are handled by the external things that populate those Items.

From the Rules page in MainUI once again click the + icon. Enter reasonable identifying information once again.

This time select “Move tagged DateTime Items to today’s date” from the list of Templates. Enter an Item tag that will be used by this rule to identify those Items that the rule needs to process. In this case I’ve chosen “totd”.

Now navigate to the Items that have hard coded times. In our case that’s ToD_NIGHT and ToD_BED. Click on “Edit” in the upper right corner. Under “Non-Semantic Tags” type in “totd” and be sure to press Enter. It should show up with a little tag icon.

Repeat for all hard coded Items.

Get Everything Running

Navigate to the Time of Day To Today Rule and run it by clicking the play icon. This ensures that the Items all have today’s date. Watch the logs for errors.

Navigate to all the Time of Day X Manager rules and run those by by clicking the play icon. This will cause the rules to start timers for today. Alternatively restart openHAB which will cause them all to run.

Fewer Rules Example

The no code example creates a ton of rules: 2N+1 where N is the number of times of day. While the number of rules is not a problem necessarily, it does clutter up the list of rules in MainUI. If you are willing to write just a little bit of code we can reduce that down to N+1 rules. We can do this by taking advantage of a feature of the Alarm Clock Rule to collapse the Time of Day X rules into one single rule.

Instead of creating one Time of Day X rule for each time of day, we will just create one and use some string parsing to extract the time of day from the Item’s name that triggered the rule to be called.

Click the + icon from the Rules page to create a new rule. Enter reasonable information in the top section.

Click on “Add Action” under “Then” and select “Run Script”.

You can choose any language of choice. However, I don’t think that Blockly has access to the variable passed to this rule by the Alarm Clock Rule. I’ll choose ECMAScript 5.1 for this example.

When one rule calls another rule, it can pass data to the called rule. This data is available in context and can be accessed by name using context.getAttribute("name");. The Alarm Clock Rule will pass a value named “triggeringItem” which contains the name of the Item that triggered the Alarm Clock Rule. Using this we can know which Alarm Clock Rule called the script and parse the time of day out of the Item name. I told you Associated Items naming would come in handy. :wink:

The following can be pasted into the code tab of a rule if you want to use it.

configuration: {}
triggers: []
conditions: []
actions:
  - inputs: {}
    id: "1"
    configuration:
      type: application/javascript
      script: >-
        var logger = (logger === undefined) ?
        Java.type("org.slf4j.LoggerFactory").getLogger("org.openhab.model.script.rules_tools.Time
        of Day") : logger;


        var timeOfDay = context.getAttribute("triggeringItem").toString().split("_")[1];

        logger.info("Transitioning to " + timeOfDay);

        events.sendCommand("TimeOfDay_Example", timeOfDay);
    type: script.ScriptAction

The JavaScript is

var logger = (logger === undefined) ? Java.type("org.slf4j.LoggerFactory").getLogger("org.openhab.model.script.rules_tools.Time of Day") : logger;

var timeOfDay = context.getAttribute("triggeringItem").toString().split("_")[1];
logger.info("Transitioning to " + timeOfDay);
events.sendCommand("TimeOfDay_Example", timeOfDay);

Now when creating the Alarm Clock rules, choose the “Time of Day Transition” rule as the “Script to Call”.

Not only does this eliminate N-1 of the total number of rules, it’s pretty simple, being only four lines of code and you get a log statement too boot.

What’s the Point?

Why did I write this tutorial? There are a number of reasons which amount to the key take aways.

  • Especially in the UI rules, often it is easier to have lots of rules than it is to figure out how to write one more generic rule. This can particularly be the case when using rules from the Marketplace.

  • For Marketplace rules writers, consider making simple rules which can interact with each other in interesting ways. In this example, we have a simple rule that schedules a timer to call another rule based on a DateTime Item and another rule to move a DateTime Item to today. Individually and independently each rule is useful in its own right. But by combining them we can achieve something as complex as the Time of Day Design Pattern.

  • When you are ready, don’t be afraid of a little bit of code. It can save you a lot of work in the long run.

  • Even though you are using a rule template, you end up with a full rule that can be edited. Don’t be afraid to look at the code that results from a template and customize it to meet your own needs.

  • For Marketplace rules writers, notice how the To Today rule uses Item tags to identify those tags it needs to operate with. Semantic tags, Item metadata and other Item properties can be used as well. A Group is not always required and might be more of a pain for the end users to set up than other alternatives.

Exercises for the Student

Feature A way to achieve it
Different times of day for weekends Add a separate set of Items and rules for the weekend. Add conditions to the rules so one set of rules are only running on weekdays and the other set only on weekends.
Fewer rules Add the ability to set a Group with a Member of trigger on the Alarm Clock Rule. Modify the code so the one instance of the rule can handle all the time of day Items. (this is on my todo but I want to use a library so am waiting for a better way to handle that).
Instead of time of day drive a different time based behavior Change the implementation of the Time of Day X rule(s) to do something beyond just commanding a Time of Day Item.
11 Likes

If anyone else is a numpty like me, you’ll be wondering where (or maybe even what) this marketplace is. :slightly_smiling_face:

You need to update to 3.2, which is a ‘milestone’ / test release. :+1:

To make your openhab 3.1 update to 3.2 you need to:

  1. Stop the openhab service sudo systemctl stop openhab.service
  2. Change the openhab repository to “testing” via:
    1. Open openhab.list for editing, from etc/apt/sources.
    2. change the word stable to the word testing then save.
  3. sudo apt-get update
  4. sudo apt-get upgrade
  5. Start the openhab service sudo systemctl start openhab.service
  6. Restart just to be safe. :sweat_smile:

If you’re seeing UNINITIALIZED HANDLER_MISSING_ERROR issues, take a look through your things/items, and see if eliminating some of them helps (it helped me), otherwise, this thread might either help you or lead you to better searches.

Anyone that’s more aware of this and thinks I’ve screwed it up, please do edit/say, and I’ll edit/add/remove the steps for my fellow dumb MFs. :sweat_smile:

We tend to recommend openHABian to most new users or users who are not super experienced with Linux. In openhabian-config you can change between stable, testing, and snapshots through menu option 40 openHAB Related → 41 openHAB Milestone.

1 Like

Aye, sounds good to me 
 I did that on one build, but this one does other things.

Definitely would do that for other builds, though! :slightly_smiling_face:


FWIW 
 I did once build my own slackware linux back in the day, and even made my own (crt) monitor driver for it 
 but 
 y’know 
 we’re not all born equal in the brain stakes 
 some people just don’t get some stuff 
 and that’s OK. :slight_smile:

Regarding the Astro configuration, apart from the Dusk one should these be set to the “Timestamp on Update” or the “Timestamp on Change” profile ?

I would assume the “Timestamp on Update” profile, because they’re DateTime items, and it should run any time the Start Time updates rather than changes. But I just didn’t see it mentioned there, and didn’t want to assume too much (even though I did :sweat_smile: ).

Also, you mention the ‘dusk’ section, does this relate to:

  1. Astro Dusk
  2. Nautic Dusk
  3. Civil Dusk
    I assumed and used #1, because that seems the most generic.

Or would it have been better to just create a new channel, just in case that is needed for other things?

Also, just curious 
 (I haven’t read further down) 
 why move away from defining NIGHT by astro?

No. Just link the DateTime Item to the Astro Channel you want to use. The Channel tells you what type of Item it needs to be linked to.

A “Trigger” type Channel cannot be linked to an Item and instead is used to trigger a rule to run.

No, Astro recalculates the date times for each event a few seconds after midnight and updates the DateTime Items linked to its Channels to the new day’s times. When the Item updates it triggers the Alarm Clock rule which sets a timer to call the script at that date and time.

It doesn’t matter. You need to figure out which dusk you care about. Wikipedia has a good set of articles on the differences between these. You may not even care about dusk at all. It’s not required. It is only mentioned in the tutorial as an example. Figuring out what times you actually care about and how to populate the DateTime Items is something you need to figure out. I can’t tell you what times and events to use. Your automation is different from mine. You don’t have to use Astro at all if you don’t want to.

The Astro binding doesn’t let you just create new Channels. It has a fixed set of Channels that it supports and you can choose among them. You can even configure them, for example create an offset. But you cannot just invent a new type of dawn Channel.

What solar event would I use? Sunset was used for EVENING. The sun has gone down by that point. But even if there were a solar event I could use, I don’t want to. I want NIGHT to start at 10:00 pm every night regardless of what the sun is doing.

Once again, the states and how they are populated above are examples. I’ve purposefully not provided lots of details about how to set up the Astro binding or the reasons why I’ve chosen different Channels and values because you aren’t supposed to just copy and paste them. You need to come up with your own that make sense in your home automation.

The rules above don’t care where or how the date time is set on the DateTime Items. That’s frankly outside the scope of this tutorial.

1 Like

I was trying to follow the example 
 I just didn’t understand some of it, hence questions.

I’ll just put a load of stuff in then see what happens, I guess. XD

Also, there’s a distinction between Timestamp on Update, and Timestamp on Change 
 which was something I suppose is still a bit up in the air.

I can’t understand the difference from the documentation, so with regards to this specific example, should this example be using Timestamp on Update, or Timestamp on Change 
 for this example 
 as an example 
 in example terms.


Also, FWIW 
 something in the chain of events (following it verbatim) wipes out any dates/times set earlier 
 so when you run the rules at the end it just uses the current time for all the values.

No. Just link the DateTime Item to the Astro Channel you want to use.

Do not use a Profile.

Profiles are not involved.

Nowhere in the tutorial above nor in the Astro binding docs are Profiles mentioned.

As I explained:

Astro recalculates the date times for each event a few seconds after midnight and updates the DateTime Items linked to its Channels to the new day’s times.

You don’t need a Profile for this.

Well of course. The docs say that the Timestamp Update Profile

This Profile will update a DateTime Item to track every change of the state of a given Channel.

Put another way, when a binding (Astro) creates an update event on an Item, regardless of what that update happens to be, the Profile will set the state of the linked DateTime Item to the current time. You’d use this, for example, to track the last time a door was opened and stuff like that.

And Astro Channel links directly to a DateTime Item. Around midnight and when OH first starts up it will update that DateTime with today’s date and time for the given event. Nothing more needs to be done to that DateTime. It’s already exactly what we want it to be, the date and time for today’s sunrise for example.

A Profile is used when what is coming from the binding is not what you need and it needs to be transformed or processed in some way. You don’t need to change anything from Astro. You don’t need a Profile.

Step back because you appear to have dived right into the deep end and are flailing around. I think there are a number of key concepts you do not understand, some perhaps you don’t even know you don’t understand.

Have you read the Concepts section of the docs? https://www.openhab.org/docs/concepts/
Is there anything there you do not understand?
Do you understand the relationship between a Thing and an Item?
Do you understand what an Item is and how an Item’s state is managed?
Do you understand what events can occur on an Item and what those states mean? Do you understand the difference between an update, change, and command?

You can’t do calculous if you don’t know algebra. Similarly you can’t be successful or even understand much of the docs in openHAB if you don’t understand the basic concepts.

Ahhhhh 
 hahahaha 
 :sweat_smile:

I completely didn’t see the option to “Configure channel”, so I saw the only way to set an offset was to use that option.

Sorry about not seeing that! :slightly_smiling_face:


I’m sorry, but these documents are extremely hard to understand 
 it’s like they’re written for university students that are studying deepest theoretical physics or something 
 it’s genuinely hard to understand half of what they’re talking about most of the time.

I’m sure that it’s fine for someone with more than half a brain, but some dumbos need more than a page of writing with some pretty pictures. Literally, reading most of these words I might a well have been slapping my face with a kipper, mate.

It’s not like it’s hard to learn stuff (I’ve been accidentally learning javascript lately due to Google Apps Script and trying to do Power Automate stuff elsewhere) by doing it 
 and I’m pretty sure if I can build a linux distro from scratch I can deal with this thing. But these documents are a cypher, written for mensa members, to do whilst they do the cryptic crossword on their other hand.

I can follow instructions ( except when I mess it up, like above :sweat_smile: ) and that will instill a lot 
 but apart from installing the thing these documents are mind bending.

Please refrain from using profanity. We are an international community with many young members and there are many who are offended by such language. We want to be welcoming to all so it’s against the rules. Please edit your post to remove it.

So, are you going to just continue to flail about trying random stuff without understanding what you are doing and why it doesn’t work, or will you accept my help by answering each of the questions I asked? They are not rhetorical.

You are missing the understanding of a number of key concepts in OH. You can’t be successful until you understand those. If you don’t know what an Item and a Thing is and how they link together and how they are used I’ve no doubt that the rest of the docs are inscrutable. They assume a base level of knowledge and undertstanding.

A thousand apologies 
 I’ll try to find the swear and edit it out now 
 I don’t remember writing one 
 I’m used to them just being blanked out in the other discourse community I’m a part of which has even younger members.

Mate 
 I’m not trying to have some weirdo fight with you 
 I’m not sure why you seem to ascribe such a harsh tone to your interactions here.

I’ve just stated that the documents are gobbledegook 
 they’re about as useful as an inflatable dart board.

If you’re really desparate for answers, then “yes” is the answer to the 3 questions after the two that I answered with the longer paragraph of my previous post. But the documents have not helped me get to that “yes” status in the slightest. Pure logic and ‘doing stuff’ managed to get me there.

You know what 
 you just seem to want to weirdly battle against stuff. I’ll take my chances with others if they have the inclination, thanks for your time, though.

Sounds like a good plug-in we should look into.

Not at all. I am frustrated because I’ve already spent a good deal of time here trying to understand what you don’t understand but I’m not fighting against you. I just wish you would give me more details and less complaining. I can’t help you if I don’t know what you don’t understand. No one can. And you’ve given no details, just disconnected questions and complaints about how hard the docs are to understand.

I’m not telling you to just go read the documents.

I’m trying to figure out what I can clarify for you and maybe learn some things that can be improved in the documents. But you are giving me nothing to work with. I could just regurgitate the docs here in a forum reply which probably won’t help you at all, or maybe you could help me to narrow down those key concepts that you don’t understand and that you are having difficulty with so I can provide more detailed or alternative explanations that might be more clear to you.

But there is one thing that is absolutely true about openHAB. You can’t not use the documents. You can’t just jump in and do stuff and hope to figure it out by doing, at least not without some basic understanding of the basics. And that seems to be the big hold up right now.

At some point you posted a question along the lines of “how do I use the DateTime from Astro?” That question shows a significant lack of understanding of what an Item is, what it does, and how it’s used by openHAB. Ideally I’d want to get from you what your understanding of what an Item is as you understand it so I can correct where necessary and fill in the blanks. The same is needed for Things, Channels, and Links.

These are the three core concepts that you need to understand. If you don’t understand those, you won’t be able to understand anything else in the docs.

2 Likes

@rlkoshak I was following along on this post to set this up but when I go to build my rule to instantiate time of day using the schedule a timer to run a script button I don’t get that option I only get the move tagged DateTime items to today’s date see below

I just installed the binding and am running on OH3.2.0.M4.

Any suggestions of troubleshooting paths I can take to get this working?

If it doesn’t show up it didn’t install. Did you watch the logs when you added the Alarm Clock Rule template? Does the Alarm Clock Rule template show as added in Settings → Automation?

@rlkoshak You called it for some reason it didn’t install. Thanks for catching my mistake! Appreciate the work you did on these!

Hi @rlkoshak, I’m finally getting back into OH after a couple of years enforced covid related hiatus and have upgraded my system to OH3.2 and have found my time of day rule needs upgrading to the above.

I’ve followed it all and happy with the process, the question I have is on a way to deal with sunrise v fixed time at certain times of the year.

For example, my ‘DAWN’ starts at sunrise, my ‘DAY’ starts at 7am, and rules fire based on this.

My issue is that for around 4 months of the year here in the UK, Sunrise / DAWN is actually later than 7am so rather than TimeofDay = DAWN and then transitioning onto DAY it is the other way round which plays havoc with my rules.

In OH2.5 rules I had a if(dawn_start.isBefore(day_start)) then else statement which determined whether to have a DAWN or just move straight into DAY. Before I do some re-writing of rules, is there a way in this example to tell the system to do something similar?

TIA

The easiest is to set the latest property on the Astro dawn channel you are using. That will prevent the Item from ever becoming anything later than that time.

You could set the latest to 06:59 and DAWN will occur no later than one minute before DAY. I worry if set it to 07:00 it will be a race condition to see whether DAWN or DAY happens first.

If you want to suppress DAWN entirely when it’s after 07:00, then add that check to the script that is called by the Alarm Clock Rule Template. You can add that as a condition in the but only if on the called script (i.e. don’t run the rule if TimeOfDay is already DAY) (assuming you have a separate rule that’s called per time of day) or you can add the logic to the Script Action of that rule to no do anything.

You wouldn’t be rewriting anything from the rule template. You’d be customizing the code called by the rule template, which is the whole intent.

Note, that I actually recommend using Time Based State Machine to drive time of day for most users since it has built in the ability to have different times of day based on the type of day (e.g. weekends, holidays, etc.). In that case you’d still have this Alarm Clock rule template drive the DAWN state and use the condition to not do anything if TimeOfDay is already DAY.

Hi Rich,
I have recently upgraded from OH2.5 to OH3.2.0 Release Build.
This is running on a Ras PI 4 8gb using Openhabian.
I have influxDB installed.
I implemented ToD rules template and managed to get it all working after a few typos.
Today I rebooted the PI to see if the persistance was working as it should, and received 3 errors in the log referring to three of the ToD managers.

2022-05-02 16:25:05.512 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID 'todAfternoonMgr' failed: TypeError: Cannot read property "class" from undefined in <eval> at line number 30
2022-05-02 16:25:05.629 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID 'todDayMgr' failed: TypeError: Cannot read property "class" from undefined in <eval> at line number 30
2022-05-02 16:25:05.629 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID 'todEveningMgr' failed: TypeError: Cannot read property "class" from undefined in <eval> at line number 30

This is the line of code in the rule at line number 30

if(time.class != type || time.getZonedDateTime().isBefore(ZDT.now())) {

Here is the rule that was generated while implementing Time of Day according to your description/process outlined above.

if(typeof(require) === "function") Object.assign(this, require('@runtime'));
var FrameworkUtil = (FrameworkUtil === undefined) ? Java.type("org.osgi.framework.FrameworkUtil") : FrameworkUtil;
var ScriptExecution = (ScriptExecution === undefined) ? Java.type("org.openhab.core.model.script.actions.ScriptExecution") : ScriptExecution;
var ZDT = (ZDT === undefined) ? Java.type("java.time.ZonedDateTime") : ZDT;

var logger = (logger === undefined) ? Java.type("org.slf4j.LoggerFactory").getLogger("org.openhab.model.script.rules_tools.Alarm Clock") : logger;

this.timer = (this.timer === undefined) ? null : this.timer;
var time = items['LocalSun_StartTime'];
var item = 'LocalSun_StartTime';
var script = 'todTransition';
var callScriptGenerator = function(data, script) {

  return function() {
    logger.debug("About to call script action");
    
    // Get the RuleManager
    this.ScriptHandler = Java.type("org.openhab.core.automation.module.script.rulesupport.shared.ScriptedHandler");
    var _bundle = FrameworkUtil.getBundle(ScriptHandler.class);
    var bundle_context = _bundle.getBundleContext()
    var classname = "org.openhab.core.automation.RuleManager"
    var RuleManager_Ref = bundle_context.getServiceReference(classname);
    var RuleManager = bundle_context.getService(RuleManager_Ref);
    RuleManager.runNow(script, true, data);
  }
}

// No alarm scheduled
var type = (typeof(require) === "function") ? DateTimeType : DateTimeType.class;
if(time.class != type || time.getZonedDateTime().isBefore(ZDT.now())) {
  logger.info("No alarm scheduled for " + item);
  if(this.timer !== null) {
    this.timer.cancel();
  }
}
// create or schedule a timer to run at the configured time
else {
  logger.info("Scheduling alarm at " + time + " for " + item);
  
  if(this.timer !== null) {
    logger.debug("Rescheduling alarm for " + time);
    this.timer.reschedule(time.getZonedDateTime());
  }
  else {
    logger.debug("Setting a new alarm for " + time);
    var map = new java.util.HashMap();
    map.put("triggeringItem", item)
    this.timer = ScriptExecution.createTimer(time.getZonedDateTime(), callScriptGenerator(map, script));
  }
}

Would you have any idea what I could have done wrong here as my level of javascript is still at beginners?

This is my first post and first attempt at using code fences etc. so please let me know if I have made any fundamental errors?

Add a logging statement to the rule to log out time. I suspect that for some reason LocalSun_StartTime doesn’t exist at the time when the rule ran. Did the rules run again a few seconds later?