# Help making a JavaScript example

**URL:** <https://community.openhab.org/t/help-making-a-javascript-example/169675>\
**Category:** Development\
**Created:** [July 3, 2026, 12:52pm UTC](https://community.openhab.org/t/help-making-a-javascript-example/169675 "2026-07-03T12:52:48Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![Nadahar](https://community.openhab.org/user_avatar/community.openhab.org/nadahar/32/194556_2.png) [@Nadahar](https://community.openhab.org/u/Nadahar)\
**Post date:** [July 3, 2026, 12:52pm UTC](https://community.openhab.org/t/help-making-a-javascript-example/169675/1 "2026-07-03T12:52:48Z")

</div>

I’m working on documenting YAML rules and rule templates, and I think I’m closed to finished.

However, I thought that it would be nice to include a JavaScript rule template example, but I have no idea how to actually write valid JavaScript rules.

I’m worried that the example is a bit terrible to, because it will check the light status every minute, but I also want to keep it reasonably simple.

Anyway, here goes what I have with Qwen-Coder generated JavaScript:

```yaml
version: 1
rules:
  "3699580b09":
    template: light-control
    label: Light Control Test
    description: Controls lights based on time.
    config:
      light_item: DemoSwitch
      end_time: 01:00
      start_time: 19:00
    triggers:
      - id: time_trigger
        config:
          cronExpression: 0 0/1 * 1/1 * ? *
        type: Cron
    actions:
      - id: light_action
        config:
          type: JavaScript
          script: |
            var item = items.getItem("DemoSwitch");
            const now = time.ZonedDateTime.now();
            if (now.isAfter(now.withTimeAtStartOfDay().plusHours(parseInt(config.start.split(':')[0])).plusMinutes(parseInt(config.start.split(':')[1]))) &&
                now.isBefore(now.withTimeAtStartOfDay().plusHours(parseInt(config.end.split(':')[0])).plusMinutes(parseInt(config.end.split(':')[1])))) {
              item.sendCommand(ON);
            } else {
              item.sendCommand(OFF);
            }
        type: Script

```

The script part obviously fails as it is now, it calls non-existing methods. However, instead of me trying to figure out how to do this in JavaScript, I was hoping that some of you that use this could chip in and help me.

I’d also only want the command to be sent if the state isn’t already correct, to not hammer the Item with commands.

Examples should be exemplary, which is why I think it’s a bad idea that I try to figure this out anyway.

edit: Please ignore `config.start` etc. suggested by Qwen, it doesn’t properly understand rule templates. Instead, the string should be used directly, e.g. `19:00`.

---

<div class="post-metadata">

**Author:** ![Nadahar](https://community.openhab.org/user_avatar/community.openhab.org/nadahar/32/194556_2.png) [@Nadahar](https://community.openhab.org/u/Nadahar)\
**Post date:** [July 3, 2026, 12:54pm UTC](https://community.openhab.org/t/help-making-a-javascript-example/169675/2 "2026-07-03T12:54:02Z")

</div>

@rlkoshak I have a feeling that you’re one of the potential people that could help out here.

---

<div class="post-metadata">

**Author:** ![Nadahar](https://community.openhab.org/user_avatar/community.openhab.org/nadahar/32/194556_2.png) [@Nadahar](https://community.openhab.org/u/Nadahar)\
**Post date:** [July 3, 2026, 2:16pm UTC](https://community.openhab.org/t/help-making-a-javascript-example/169675/3 "2026-07-03T14:16:11Z")

</div>

With some help from Gemini, I got to this, which at least runs without errors.

```yaml
version: 1
rules:
  "3699580b09":
    template: light-control
    label: Light Control Test
    description: Controls lights based on time.
    config:
      light_item: DemoSwitch
      end_time: 01:00
      start_time: 19:00
    triggers:
      - id: time_trigger
        config:
          cronExpression: 0 0/1 * 1/1 * ? *
        type: Cron
    actions:
      - id: light_action
        config:
          type: JavaScript
          script: |
            var item = items.getItem("DemoSwitch");
            const now = time.ZonedDateTime.now();

            // Build absolute ZonedDateTime objects for today using the raw string fragments
            let startTime = time.toZDT("19:00");
            let endTime = time.toZDT("01:00");

            // Handle time windows that cross midnight (e.g., 19:00 to 01:00)
            if (endTime.isBefore(startTime)) {
              if (now.isBefore(endTime)) {
                // If it is early morning (e.g., 00:30), move the start boundary to yesterday
                startTime = startTime.minusDays(1);
              } else {
                // If it is evening (e.g., 20:00), move the end boundary to tomorrow
                endTime = endTime.plusDays(1);
              }
            }

            // Verify if 'now' sits inside our execution window
            if (now.isAfter(startTime) && now.isBefore(endTime)) {
              // Only send command if the light isn't already ON
              if (item.state !== "ON") {
                item.sendCommand("ON");
              }
            } else {
              // Only send command if the light isn't already OFF
              if (item.state !== "OFF") {
                item.sendCommand("OFF");
              }
            }
        type: Script

```

I still don’t know if this is “good example material” though. Is this written reasonably, or should things be done differently in an example?

---

<div class="post-metadata">

**Author:** ![JustinG](https://community.openhab.org/user_avatar/community.openhab.org/justing/32/55948_2.png) [@JustinG](https://community.openhab.org/u/JustinG)\
**Post date:** [July 3, 2026, 2:49pm UTC](https://community.openhab.org/t/help-making-a-javascript-example/169675/4 "2026-07-03T14:49:19Z")

</div>

> [@Nadahar](#):
>
> I’d also only want the command to be sent if the state isn’t already correct, to not hammer the Item with commands.

JSScripting library has a built-in option for this: `sendCommandIfDifferent`

> **[sendCommandIfDifferent(value) → {boolean} - Item - openHAB JS](https://openhab.github.io/openhab-js/items.Item.html#sendCommandIfDifferent)**
>
> Item state as boolean or null if state is not boolean-compatible. | JSDoc for openHAB JS - the openHAB JavaScript Helper Library

> [@Nadahar](#):
>
> I still don’t know if this is “good example material” though.

The only thing about it seems a little off is the every minute cron trigger. I would think that a more common example for beginners would be connecting a light to a sensor event, especially a motion sensor, or to an astro event.

I have a nice simple rule that turns on the light in my pantry when the door is open and turns it off again when the door is closed which has the advantage over a motion control example of not getting into the issue of accurate presence detection.

> [@Nadahar](#):
>
> Is this written reasonably

Looks pretty good to me. I would tweak only two minor things:

> [@Nadahar](#):
>
> `var item = items.getItem("DemoSwitch");`

Since you are using `const` and `let` everywhere else, this should probably be `let` instead of `var`.

> [@Nadahar](#):
>
> ```auto
> if (now.isAfter(startTime) && now.isBefore(endTime)) {
> // Only send command if the light isn't already ON
> if (item.state !== "ON") {
> item.sendCommand("ON");
> }
> } else {
> // Only send command if the light isn't already OFF
> if (item.state !== "OFF") {
> item.sendCommand("OFF");
> }
> }
> 
> ```

Between `sendCommandIfDifferent` and a ternary expression, I would condense this to

```auto
let turnOn = now.isAfter(startTime) && now.isBefore(endTime);
item.sendCommandIfDifferent(turnOn ? "ON" : "OFF");

```

---

<div class="post-metadata">

**Author:** ![Nadahar](https://community.openhab.org/user_avatar/community.openhab.org/nadahar/32/194556_2.png) [@Nadahar](https://community.openhab.org/u/Nadahar)\
**Post date:** [July 3, 2026, 2:57pm UTC](https://community.openhab.org/t/help-making-a-javascript-example/169675/5 "2026-07-03T14:57:12Z")

</div>

> [@JustinG](#):
>
> JSScripting library has a built-in option for this: `sendCommandIfDifferent`

Thanks, I’ll see if I can figure that out.

> [@JustinG](#):
>
> The only thing about it seems a little off is the every minute cron trigger. I would think that a more common example for beginners would be connecting a light to a sensor event, especially a motion sensor, or to an astro event.

The point is that it’s an example of how to use a rule template, so I want it to be simple to not “take focus away” from the basics. Running a cron every minute might be excessive, but given that it is precompiled, it should actually be a very light load on the system. What is “worse” is that there will be constant “rule executed” events, but again, I need to keep the example simple.

> [@JustinG](#):
>
> Since you are using `const` and `let` everywhere else, this should probably be `let` instead of `var`.

Good point.

> [@JustinG](#):
>
> Between `sendCommandIfDifferent` and a ternary expression, I would condense this to

I’ll give it a try.

To demonstrate how the examples are being used, here’s a preview:

> **[Example - YAML Rule Templates](https://deploy-preview-2737--openhab-docs-preview.netlify.app/docs/configuration/yaml/ruletemplates.html#example)**
>
> This page describes the ruleTemplates element for YAML Configuration. | a vendor and technology agnostic open source automation software for your home

I want the focus to be on the placeholders and how they are substituted.

---

<div class="post-metadata">

**Author:** ![rlkoshak](https://community.openhab.org/user_avatar/community.openhab.org/rlkoshak/32/75251_2.png) [@rlkoshak](https://community.openhab.org/u/rlkoshak)\
**Post date:** [July 3, 2026, 3:29pm UTC](https://community.openhab.org/t/help-making-a-javascript-example/169675/6 "2026-07-03T15:29:57Z")

</div>

> [@Nadahar](#):
>
> The point is that it’s an example of how to use a rule template, so I want it to be simple to not “take focus away” from the basics.

Linking the trigger to a property of the template is a pretty basic thing for a template.

What I would do with this example:

```yaml
version: 1
rules:
  "light-control-template":
    template: light-control
    label: Light Control Template
    description: Controls lights based on a light sensor
    config:
      light_item: DemoSwitch
      sensor_item: DemoSensor
      end_time: 01:00
      start_time: 19:00
    triggers:
      - id: item_trigger
        config:
          item: {{sensor_item}}
        type: ItemChanged
    actions:
      - id: light_action
        config:
          type: JavaScript
            if(time.toZDT().isBetweenTimes("{{start_time}", "{{end_time}}")){
              items["{{light_item}}"].sendCommandIfDifferent("ON");
            }
            else {
              items["{{light_item}}"].sendCommandIfDifferent("OFF");
            }
        type: Script

```

- give it a meaningful UID and name
- an Item trigger is going to be much more commonly used than a cron trigger so that would make a better trigger for the example
- `isBetweenTimes()` handles the case when the start time is after the end time for you and it parses the times for you (i.e. calls time.toZDT() on the arguments)

If I were writing for me instead of for an example I’d use this one liner:

```js
  items["{{light_item}}"].sendCommandIfDifferent((time.toZDT().isBetweenTimes("{{start_time}}","{{end_time}}")) ? "ON" : "OFF");

```

---

<div class="post-metadata">

**Author:** ![Nadahar](https://community.openhab.org/user_avatar/community.openhab.org/nadahar/32/194556_2.png) [@Nadahar](https://community.openhab.org/u/Nadahar)\
**Post date:** [July 3, 2026, 3:38pm UTC](https://community.openhab.org/t/help-making-a-javascript-example/169675/7 "2026-07-03T15:38:40Z")

</div>

> [@rlkoshak](#):
>
> - give it a meaningful UID and name

This was a generated rule, the UID and labels aren’t the ones used in the documentation.

> [@rlkoshak](#):
>
> - an Item trigger is going to be much more commonly used than a cron trigger so that would make a better trigger for the example

That depends I guess, but I agree that it’s nice to not have the cron timer in the example, so I can change that. That said, if I wanted to have a simple template for switching lights on and off at specific times, I’m not sure that I wouldn’t just use a cron timer. What would the Item be?

> [@rlkoshak](#):
>
> - `isBetweenTimes()` handles the case when the start time is after the end time for you and it parses the times for you (i.e. calls time.toZDT() on the arguments)

I’ll take your word for it, which simplifies everything a whole lot.

---

<div class="post-metadata">

**Author:** ![rlkoshak](https://community.openhab.org/user_avatar/community.openhab.org/rlkoshak/32/75251_2.png) [@rlkoshak](https://community.openhab.org/u/rlkoshak)\
**Post date:** [July 3, 2026, 3:48pm UTC](https://community.openhab.org/t/help-making-a-javascript-example/169675/8 "2026-07-03T15:48:24Z")

</div>

> [@Nadahar](#):
>
> That said, if I wanted to have a simple template for switching lights on and off at specific times, I’m not sure that I wouldn’t just use a cron timer. What would the Item be?

In that case just trigger at the start time and the end time

```yaml
version: 1
rules:
  "light-control-template":
    template: light-control
    label: Light Control Template
    description: Controls lights based on a light sensor
    config:
      light_item: DemoSwitch
      end_time: 01:00
      start_time: 19:00
    triggers:
      - id: start_trigger
        config:
          time: {{start_time}}
        type: TimeOfDay
      - id: end_trigger
        config:
          time: {{end_time}}
        type: TimeOfDay
    actions:
      - id: light_action
        config:
          type: JavaScript
            if(time.toZDT().isBetweenTimes("{{start_time}", "{{end_time}}")){
              items["{{light_item}}"].sendCommandIfDifferent("ON");
            }
            else {
              items["{{light_item}}"].sendCommandIfDifferent("OFF");
            }
        type: Script

```

But an example that does use an Item trigger and the Item is chosen by a configuration property will be the most common use case.

The rule will actually run after the trigger by few milliseconds so the isBetweenTimes() comparison should still work.

> [@Nadahar](#):
>
> I’ll take your word for it, which simplifies everything a whole lot.

> **[isBetweenTimes(start, end) - JavaScript Scripting - Automation](https://next.openhab.org/addons/automation/jsscripting/#isbetweentimes-start-end)**
>
> This add-on provides support for JavaScript (ECMAScript 2025+) that can be used as a scripting language within automation rules. It is based on GraalJS (opens new window) from the GraalVM project (opens new window). | This add-on provides support for...

---

<div class="post-metadata">

**Author:** ![Nadahar](https://community.openhab.org/user_avatar/community.openhab.org/nadahar/32/194556_2.png) [@Nadahar](https://community.openhab.org/u/Nadahar)\
**Post date:** [July 3, 2026, 4:01pm UTC](https://community.openhab.org/t/help-making-a-javascript-example/169675/9 "2026-07-03T16:01:33Z")

</div>

The point isn’t if the rules are useful, but if the mechanisms of using templates are clear. So, I’ve modified it to use the sensor item.

I actually have a somewhat similar rule in use (except that it gradually adjusts the light levels), and I think it’s actually run by a cron trigger. The reason for that, is that I don’t want it to only control the lights “at the thresholds”, but in between as well. In my “real” case, there’s an Item that enables or disables “automatic lighting”, and if it’s enabled, it will start controlling the lights - and override any manual adjustments made (it’s a bit more complicated, it will only override it if the level is set to low when it’s increasing or too high when it’s descending). For such a scenario, I do a check every 2 minutes I think.

Anyway, using the “sensor Item” has revealed a bug I think, the rule won’t initialize because:

```auto
Getting handler 'core.ItemStateChangeTrigger' for module 'item_trigger' failed: Cannot invoke "String.contains(java.lang.CharSequence)" because "this.itemName" is null

```

I have no suitable “sensor Item”, so I just set it to a string Item, but I can’t see why the rule shouldn’t still be accepted. This is the trigger:

```yaml
    triggers:
      - id: item_trigger
        config:
          item: DemoString
        type: ItemChanged

```

Did I do something obviously wrong here, or is there something fishy going on?

edit: Forget the error, it was just a wrong property name:

```yaml
    triggers:
      - id: item_trigger
        config:
          itemName: DemoString
        type: ItemChanged

```

..works.

---

<div class="post-metadata">

**Author:** ![Nadahar](https://community.openhab.org/user_avatar/community.openhab.org/nadahar/32/194556_2.png) [@Nadahar](https://community.openhab.org/u/Nadahar)\
**Post date:** [July 3, 2026, 4:08pm UTC](https://community.openhab.org/t/help-making-a-javascript-example/169675/10 "2026-07-03T16:08:28Z")

</div>

Updated preview is ready:

> **[Example - YAML Rule Templates](https://deploy-preview-2737--openhab-docs-preview.netlify.app/docs/configuration/yaml/ruletemplates.html#example)**
>
> This page describes the ruleTemplates element for YAML Configuration. | a vendor and technology agnostic open source automation software for your home

---

<div class="post-metadata">

**Author:** ![rlkoshak](https://community.openhab.org/user_avatar/community.openhab.org/rlkoshak/32/75251_2.png) [@rlkoshak](https://community.openhab.org/u/rlkoshak)\
**Post date:** [July 3, 2026, 4:08pm UTC](https://community.openhab.org/t/help-making-a-javascript-example/169675/11 "2026-07-03T16:08:32Z")

</div>

> [@Nadahar](#):
>
> (except that it gradually adjusts the light levels), and I think it’s actually run by a cron trigger.

That makes sense to use a cron trigger for that because the light needs to change brightness/color over time. But this is a simple ON/OFF at a certain time. So unless there is some reason you want the make sure the light is ON or OFF every minute, it’s better to use discrete triggers rather than a cron trigger. But in your use case, you _do_ have a reason to check every minute or so which makes a cron trigger very appropriate.

Stuff like this all depends on the details.

Looking at the latest lighting example, it doesn’t actually make much sense. We should use the state of the sensor somehow in the action too. Something like:

```js
            if(time.toZDT().isBetweenTimes("{{start_time}", "{{end_time}}") 
               && items["sensor_item"].quantityState.lessThan("1400 lx")){
              items["{{light_item}}"].sendCommandIfDifferent("ON");
            }
            else {
              items["{{light_item}}"].sendCommandIfDifferent("OFF");
            }

```

Otherwise the sensor isn’t actually doing anything useful here.

---

<div class="post-metadata">

**Author:** ![Nadahar](https://community.openhab.org/user_avatar/community.openhab.org/nadahar/32/194556_2.png) [@Nadahar](https://community.openhab.org/u/Nadahar)\
**Post date:** [July 3, 2026, 5:20pm UTC](https://community.openhab.org/t/help-making-a-javascript-example/169675/12 "2026-07-03T17:20:09Z")

</div>

Anybody that wants to help review this so that we can get it into the documentation, the PR is here:

> <https://github.com/openhab/openhab-docs/pull/2737>
>
> I'm working on creating corresponding sections for rules and rule templates that… exist for other YAML definitions.

Except for that, thank you both for the help, I consider this “resolved”.

---

<div class="post-metadata">

**Author:** ![system](https://community-openhab-org.s3-eu-central-1.amazonaws.com/original/2X/6/6a52f2ac5d00e4c7b50471a354b3a9221188be90.png) [@system](https://community.openhab.org/u/system)\
**Post date:** [August 14, 2026, 9:20am UTC](https://community.openhab.org/t/help-making-a-javascript-example/169675/13 "2026-08-14T09:20:16Z")

</div>

This topic was automatically closed 41 days after the last reply. New replies are no longer allowed.
