openHAB 5.2 Rule Templates Best Practices

With the release of openHAB 5.2 we now have full coverage for YAML file based configs, including for rule templates. Please go to How and Why to Write a Rule Template (revisited) and read down to the “How?” section for what a rule tempalte is and why you might want to use one. This tutorial will cover the “How?” using the new YAML file formats along with some recommendations for users who intend to post templates to the marketplace.

How does one write a template?

Good news, in the new YAML format a rule template is basically just a rule with a few minor differences. This becomes important later because it means converting a rule into a rule template is relatively easy.

This tutorial is going to assume one is mainly using MainUI for rules development. But one could easily do it all by hand coding the YAML and bypassing MainUI.

But first, the syntax is documented at YAML Rule Templates | openHAB.

Limitations

Anything that can be done in a rule can be done with a rule template. However, there are some limitations:

  • one cannot change the type of a rule trigger using a property. You can change the data used by the trigger though. So for example, you cannot change the rule’s trigger type from Changed to Updated but you can change the Item the trigger monitors for changes or updates.
  • all parameters come into the rule via a simple find-and-replace operation so additional processing may be required in the rule (for example if a parameter selects multiple Items, the comma separated list of Item names will need to be split into an array of Strings for use in the rule)
  • The marketplace only supports one rule template per file and therefore only one per posting to the forum. However, the YAML file format does support any number of ruleTemplates in one file, and you can define other entities in the same file (e.g. Items, Things, Rules, etc.). You can post any number of rule templates in one YAML posting on the marketplace. However, you cannot post other entities in the same YAML (e.g. Rules, Items, Things, Widgets, etc.), only rule templates.

Structure

Please see the link above for the overall structure of a YAML rule template. It is essentially the same as a rule with the following changes/additions:

  • they are defined under a ruleTemplates: root element
  • there is a configDescrtiption section
  • you use {{confName}} as a placeholder that gets replaced with what the user entered for that config parameter (“confName” is the <parameter_name>).

There are several examples in the docs linked to above. Here is an additional example:

version: 1

ruleTemplates:
  ohrt-upgradeCheck:
    label: openHAB Upgrade Check
    description: Runs at midnight and checks to see if the current version of OH differes from the latest release
    tags:
      - OHRT
      - Version_1.0
    configDescriptions:
      curr:
        label: Current Version Item
        description: Item that holds the current running verison of OH.
        context: item
        required: true
        type: TEXT
        filterCriteria:
          - name: type
            value: String
      latest:
        label: Latest Version Item
        description: Item that holds the latest published version of OH.
        context: item
        required: true
        type: TEXT
        filterCriteria:
          - name: type
            value: String
      up:
        label: Upgrade Available Item
        description: Item that will be set to ON when the upgrade is available
        context: item
        required: true
        type: TEXT
        filterCriteria:
          - name: type
            value: Switch
    triggers:
      - id: "midnight_trigger"
        label: Midnight
        description: Three minutes after midnight to avoid conflicts with other rules
        type: timer.TimeOfDayTrigger
        config:
          time: 00:03
    actions:
      - id: "update_check_action"
        label: "Update Check"
        description: Checks GitHub for the latest release and compares to running version
        type: Script
        config:
          type: javascript
          script: |
            var loggerBase = 'org.openhab.automation.ohrt-upgradeCheck.'+ruleUID;
            console.loggerName = loggerBase;
            //osgi.getService('org.apache.karaf.log.core.LogService').setLevel(console.loggerName, 'DEBUG');

            // Current Version
            var currVersion = Java.type('org.openhab.core.OpenHAB').version;

            // Latest Release
            var releasePage =
            actions.HTTP.sendHttpGetRequest('https://api.github.com/repos/openhab/openhab-distro/releases/latest');
            var parsed = JSON.parse(releasePage);
            var latestVersion = parsed.tag_name;

            items['{{curr}}'].postUpdate(currVersion);
            items['{{latest}}'].postUpdate(latestVersion);
            var upgradeAvail = (currVersion == latestVersion) ? "OFF" : "ON"
            items['{{up}}'].postUpdate(upgradeAvail);
            if(upgradeAvail == "ON") console.info( 'A new version of openHAB is available! Curr Version: ' + currVersion + ' Latest Release: ' + latestVersion );
            else console.debug( 'You are on the latest version: ' + latestVersion );

Identity

Here we have three fields which are used to uniquely identify the rule template:

  • <template_uid>: The root element of the rule template definition is the unique identifier for the rule template. Take care to make this very unique when posting to the marketplace to avoid colliding with other rule templates already posted.
  • label: This is the “title” of the rule template as it will appear on the new rule page
  • description: This is the description.
  • tags: These will be added to every rule created from this template.

These are shown to the end users as follows.

2025-12-03_15-23

configDescriptions

This is where you define your template parameters. For more details and examples of just about everything you can do with parameters for both UI Widgets and Templates see Parameter Playground . Note you can install this UI Widget for your reference and experimentation.

This particular config appears to the end users as this. The context controls what type of UI widget is presented to the user. In this case, context: item presents an Item picker and the filterCritera should limit the Item to just those of the given type.

In the YAML, the name of the config parameters are the root element to the section. In the above example you should see three parameters being defined: curr, latest, and up.

Applying Parameters

When a rule is created based on a template, at the time of creation a find-and-replace is performed to insert the parameters into the rule. The place holders are denoted with {{ }} with the name of the parameter. For example, any place I want the name of the Item selected for curr to be used, I’d include {{curr}}. If I selected the Item named CurrVersion then {{curr}} will be replaced with CurrVersion.

You can use substitutions in the config sections of a trigger or condition or action and anywhere in a script.

This is how you enable the rules created from the tempaltes to be configured.

How Do I Develop a Rule Template?

This is my new and improved process.

Develop the Rule

Develop your rule. Not all ways to develop a rule will work as YAML so choose one of:

  • develop the rule in MainUI (only choice for Blockly)
  • develop the rule as YAML
  • Rules DSL but do not use imports nor global variables

When you click on the “code” tab for the rule in MainUI if you see a blue “YAML” button at the bottom left the rule can be converted to a rule template following this tutorial. If not, it is created in a way that cannot be automatically converted to the YAML format.

How ever you choose to develop the rule, obtain the YAML format for that rule by clicking on that blue button. If you developed it as YAML to begin with you can move to the next step. The YAML you see in the code tab is the new YAML file format.

Convert the Rule to a Template.

Copy the YAML under a ruleTemplates: section. Add a configDescriptions section and add your parameters. Insert your replacement placeholders in the rest of the rule where the parameters should be inserted.

That’s pretty much it. Save this file to the $OH_CONF/yaml folder. You should see a line in openhab.log when the template is successfully loaded.

2026-07-06 16:36:04.542 [INFO ] [aml.internal.YamlModelRepositoryImpl] - Updating YAML model yaml/templates/marketplace-templates/ohrt-upgradeCheck.yaml

Create a Rule from a Template

  • In the UI you can choose + to create a new rule and select the template from the list in the middle. Then fill in the properties and “create rule”.
  • In a YAML file you can add your rule as normal but include the template element with the UID of the template and if there are parameters, a config section with values for the properties. See YAML Rules | openHAB for details.

Update the Template

If you’ve developed a rule template, only modify the rule by first updating the rule template and then regenerate the rule(s) created from the template (reload the YAML file or in the UI click the purple circular arrow icon).

This greatly improves the edit/test loop compared to the past procedures.

Sharing to the Marketplace

I recommend the following tips when developing a rule template for the marketplace:

  • As mentioned above, only one template per file.
  • You can paste the contents of the file in the appropriate part of the forum posting template or post a link to the raw contents of the file (see below for tips on using GitHub for this)
  • Make use of the tags. I add “OHRT” to make it easier to identify rules created from my templates and “Version” to keep track of which version users of my templates are running. No longer must they open the script action to see what version of the template the rule was created from.
  • Make sure to set the versioning on the title of the forum posting. These templates will not work for versions of OH < 5.2.
  • If using a link instead of pasting the code into the forum posting, don’t forget to post the link to the raw version of the YAML.
  • If you have more than a couple of parameters or a long template, put all the parameter substitution near the top by creating a bunch of constant variables.
  • Avoid the use of wrapper concepts in JS (e.g. const) to have maximum compatability.

Tips for using Git

I publicly source control my rule templates so others can contribute to them too. I’ve found the following procedure to work the best for me.

Cloning the repo

Now that the rule templates can be loaded from files, clone your repo as a subfolder under $OH_CONF/yaml. OH reads sub-folders and will ignore non YAML files.

If your repo has a bunch of other stuff in it like mine does, you can do a sparse checkout. For example, these are the commands I use.

cd $OH_CONF/yaml

# Clone the repository without downloading files
git clone --no-checkout git@github.com:rkoshak/openhab-rules-tools.git
mv openhab-rules-tools templates
cd templates

# Enable sparse checkout
git sparse-checkout set --no-cone
git sparse-checkout set "marketplace-templates/*"

# Define your target 
git sparse-checkout set marketplace-templates

# Download the contents
git checkout main

This lets your edit the templates and deploy them to run in openHAB in the same place. As you edit and save, you can regenerate the rule(s) and see and test the changes as you edit.

Once you are happy, you can commit the changes and push them to your repo where they will be automatically be picked up by your forum posting.

Testing the Forum Posting

The only thing you cannot test locally is whether the rule template forum posting is correct and the template can be successfully installed. This should only need to be done once per posting. Once you’ve got that working, as long as your local YAML file works user should be able to install it from that point forward.

To test the forum posting is correct:

  1. remove your local copy of the template or change it’s ID and name
  2. install the rule template from the add-on store
  3. create a rule based on the installed template

If that all worked you can now delete the rule created in 3, removed the template installed in step 2 and restore your local rule template file.

From this point forward you can edit your local development version of the template, regenerate your rules from that template and as needed commit and push your changes to your git repo. Don’t forget to update the version section of the forum posting and change the version tag when you commit and push changes. If you are careful not to mess with the template of the forum posting you need no longer post the template and install it just to see if it works. If it works locally it will work posted to the forum.

TL;DR My development process

  1. sparse clone my OHRT repo to $OH_CONF/yaml so only the rule templates are downloaded (only needs to be done once)
  2. Develop my rule in the UI (you could develop in a YAML file if you choose)
  3. Copy the YAML code from MainUI from the code tab into a new file in the cloned folder in $OH_CONF/yaml.
  4. Change rules: to ruleTemplates: in the new file.
  5. Add a configDescriptions section with the parameters.
  6. Add the parameter substitution fields.
  7. Test the template by creating a rule from it, correct and edit until satisfied (regenerate the test rule after each change, you do not need to reselect the parameters for each regeneration).
  8. Commit the template to my GitHub repo.
  9. Create the forum posting.
  10. Test the forum posting can be installed usign the procedure above.
  11. Restore my local copy of the template for further development.

I kind of wrote this in a hurry. I may come back and edit it later. As always, ask if anything is not clear.

Have you tested this and found it not to work? My intention when I wrote the code was that multiple rule templates should be supported per YAML file. What isn’t supported is mixing different element types in the same marketplace add-on, like e.g. a rule template and a UI widget as “one add-on”.

A tip here is to press the Copy File Definition button on the bottom of the “Design” tab if a rule can’t be expressed as a certain format, and you will be told why with a dialog like this:

It might be something trivial that can be changed easily, that said YAML can handle most rules except SimpleRules and DSL rules with shared context.

Maybe I misunderstood this, but to make a “stub” in YAML, add a rule element, specify UID, label and template UID, in additions to the config section. A rule will be instantiated when the file is parsed.

No, I thought you told me it wont work. It it will work that would be great! I don’t have a use for it just this moment but I have in the past.

Maybe I misunderstood. I’ll remove that from the OP and will assume it works until I know otherwise.

:+1:

That’s what I meant. I clearly mangled it. That’s what I get for being in a hurry. I’ll fix it above too.

Hi,
I have an idea for a rule template. There, items that serve as triggers are to be selected with “multiple: true”. How can I use them.

    configDescriptions:
      Quelle:
        label: Sensoren
        context: item
        required: true
        multiple: true
        type: TEXT
        filterCriteria:
          - name: type
            value: Number

Experiments with

    triggers:
      - id: item_trigger
        config:
          groupName: "{{Quelle}}"
        type: MemberChanged
AND	
    triggers:
      - id: item_trigger
        config:
          itemName: "{{Quelle}}"
        type: ItemChanged
Group '[Item1, Item2]' needed for rule 'aaTest' is missing. Trigger 'item_trigger' will not work.
Item '[Item1, Item2]' needed for rule 'aaTest' is missing. Trigger 'item_trigger' will not work.

Unfortunately you can’t. The selection comes over as a comma separate list of the names of the Items you selected. They would need to be parsed out and processed individually which can only be done inside a script. You can’t do that from a trigger.

One idea that might work is to add some code to a script action that programattically adds triggers to the rule but that would be awkward at best and likely pretty brittle.

The best approach is to put all the triggering Items into a Group and have the user select that Group.

It would be less brittle to have the rule create the Group and add the selected Items as members to that Group. But it would still be just as awkward (i.e. the user needs to manually run the rule before the rule becomes fully functional). It would also only work if the Items are managed and not defined in files.