Requesting Rule Template Ideas

OK, I still have a couple ideas left to implement but I wanted to open up a request for ideas to the community for ideas to implement as rule templates.

For those who are not on the latest milestones a Rule Template is the “skeleton” of a Rule that can be installed from the Marketplace. Then you the user can create one or more rules from that template. A Rule template will have zero of more parameters that can be set to customize the behavior of the rule.

For example, I’ve posted Threshold Alert. This Rule Template implements a rule that will call another rule when one or more Items exceed or fall below a threshold. When you create a rule from this template you can set the Group with all the Items to monitor, the maximum periodicity to reporting (e.g. don’t call the rule more than once every 8 hours) as well a a do not disturb period (e.g. so you don’t get alerts at night).

With this template, you can create one rule to monitor your temperature Items to run a rule you’ve written when one falls below a 60 deg F no more than once every five minutes and another one that calls a different rule you’ve written when a battery falls below 25% but nor more than once a day and never between 22:00 and 08:00.

Look through the other templates posted at Rule Templates - openHAB Community.

OK, now you know what a rule template is, how they are used, the sorts of things they can do, and what has already been implemented, what would you like to see implemented? What ideas do you have? If you want to write it I’ll help. If you don’t want to write it I or someone else might give it a try.

At this moment in time writing rule templates is a bit manual and somewhat of a pain but things are getting better. And as it does get better it would be nice to have a backlog of good ideas to start implementing and testing out the new goodness that is the Marketplace.

1 Like

I’m still on 3.1 and haven’t done much with UI rules, so I haven’t tried out the marketplace yet.

Would it be worthwhile to make a template for enabling/disabling a thing via the REST API? Or does it require too much user input due to the API token and HTTP request? I’ve found this to be useful functionality, but it was tricky to figure out the first time.

I’ve already posted a rule template that will check Things periodically and call another rule with all the Things that meet a given criteria. I don’t think one would need to go through the REST API to disable those Things.

But what you are asking for would be something more along the lines of a library not a rule template. What would trigger this rule? How would one identify which Thing or Things to disable?

A rule template is a way to create and customize a fully functional rule, not provide a function you can call in a rule that you’ve written.

For example, here is what you’d see when creating a rule from the Alarm Clock rule template.

You give it the DateTime Item that has the alarm time and the ID of the script to call at that Item’s date time. Once you set the required properties and hit save you end up with the following rule:

configuration:
  script: alarm_script
  alarmTime: AlarmClock
triggers:
  - id: "1"
    configuration:
      itemName: AlarmClock
    type: core.ItemStateChangeTrigger
  - id: "3"
    configuration:
      startlevel: 100
    type: core.SystemStartlevelTrigger
conditions: []
actions:
  - inputs: {}
    id: "2"
    configuration:
      type: application/javascript
      script: >-
        // Change to ID of the Script Rule


        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['AlarmClock'];

        var item = 'AlarmClock';

        var script = 'alarm_script';

        var callScriptGenerator = function(data, script) {

          return function() {
            logger.debug("About to call script action");
            
            // Get the RuleManager
            var _bundle = FrameworkUtil.getBundle(scriptExtension.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

        if(time.class != DateTimeType.class || 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));
          }
        }
    type: script.ScriptAction

It’s a fully realized and self contained rule. In this specific case I chose the Item that the Android App populates with the next alarm time and the script that it calls is:

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


        // Alarm clock code goes here

        logger.info("The alarm went off for " + context.getAttribute("triggeringItem") + "!");

        if(items["TimeOfDay"] == "BED" || items["TimeOfDay"] == "NIGHT") {
          logger.info("The alarm went off and it's dark, transitioning to MORNING")
          events.sendCommand("TimeOfDay", "MORNING");
        }

        else {
          logger.warn("The alarm went off but it's not BED or NIGHT")
        }
    type: script.ScriptAction

This second rule is the one I need to write. It’s what gets called by the rule created from the template. Thus, with the rule template I’m able to schedule the execution of a rule using the state of a DateTime Item by choosing the Item and the rule to call, no coding required (and you can see it’s rather complicated code).

That’s the sort of thing I’m looking for ideas to do.

I’m also interested in library functions too, but that’s a lower priority and will wait until the GraalVM Helper Library is included in the add-on (which is a work in progress) so I know what is already implemented there, and the Marketplace implements a way to distribute such libraries.

1 Like

Gotcha. I saw your Thing Status rule, which is what made me think of this. Definitely makes more sense as a library.

As always, thanks for your efforts, Rich!

Is this too simple for what you have in mind?

rule "member of colourpicker group"
		when
			Member of ColourPickers received command
		then
	
		 
		logInfo("Colour","Colour  = "+triggeringItem.name.toString+" Changed to "+triggeringItem.state.toString)
		if (triggeringItem.state.toString == "ON") {sendCommand(triggeringItem.name.toString,"0,0,100")}
		if (triggeringItem.state.toString == "OFF") {sendCommand(triggeringItem.name.toString,"0,0,0")}
		else
		{
				var HSBType hsbValue = triggeringItem.state as HSBType

		var int redValue = hsbValue.red.intValue
		var int greenValue = hsbValue.green.intValue
		var int blueValue = hsbValue.blue.intValue

		
		var RED = triggeringItem.name+"_RED"
		var GREEN = triggeringItem.name+"_GREEN"
		var BLUE = triggeringItem.name+"_BLUE"
	
		
		
		logInfo("Colour",triggeringItem.name.toString+" HSB Value = "+hsbValue+"\nRGB Values \n"+RED+" = "+redValue+"% \n"+GREEN+" = "+greenValue+"%\n"+BLUE+" = "+blueValue)	
		
		
		sendCommand(RED,redValue.toString)
		sendCommand(GREEN,greenValue.toString)
		sendCommand(BLUE,blueValue.toString)
		}

		end

Which works with groups of items with a colourpicker and individual channels.

Group	ColourPickers		"All Colour Pickers"


// Edit the following to suit the Dimmer channels in use - Any colour item should be put into the (ColourPickers) group
	
	Color	BathroomColour			"Bathroom Colour"		<colorpicker>	(ColourPickers)	{ga="light",	alexa="BrightnessController.brightness,PowerController.powerState,ColorController.color"}
	Dimmer	BathroomColour_RED  	"Bathroom Red"					<slider>		{channel="velbus:vmb4dc:VelbusNetworkBridge:BF:CH1"}
	Dimmer	BathroomColour_GREEN  	"Bathroom Green"				<slider>		{channel="velbus:vmb4dc:VelbusNetworkBridge:BF:CH2"}
	Dimmer	BathroomColour_BLUE  	"Bathroom Blue"					<slider>		{channel="velbus:vmb4dc:VelbusNetworkBridge:BF:CH3"}
	Dimmer	BathroomColour_WHITE  	"Bathroom White"				<slider>		{channel="velbus:vmb4dc:VelbusNetworkBridge:BF:CH4", ga="Light" [roomHint="Bathroom"], alexa="PowerController.powerState,BrightnessController.brightness"}



	Color	MidRoomColour		"Middle Bedroom Colour"		<colorpicker>	(ColourPickers)	{ga="light",	alexa="BrightnessController.brightness,PowerController.powerState,ColorController.color"}
	Dimmer	MidRoomColour_RED    	"Middle Bedroom Red"					<slider>					{channel="velbus:vmb4dc:VelbusNetworkBridge:D2:CH1"}
	Dimmer	MidRoomColour_GREEN   	"Middle Bedroom Green"					<slider>					{channel="velbus:vmb4dc:VelbusNetworkBridge:D2:CH2"}
	Dimmer	MidRoomColour_BLUE    	"Middle Bedroom Blue"					<slider>					{channel="velbus:vmb4dc:VelbusNetworkBridge:D2:CH3"}
Dimmer	MidRoomColour_WHITE  		"Middle Bedroom White"								<slider>					{channel="velbus:vmb4dc:VelbusNetworkBridge:D2:CH4", ga="Light" [roomHint="Middle Bedroom"], alexa="PowerController.powerState,BrightnessController.brightness"}

I’m also looking for an RGBW rule to use with a colour picker, but I don’t know how to get a White value from the HSL without washing out the other colours.

I also have a rule that Monitors the White channel for commands and sets the respective Colourpicker to Black

Simple isn’t a problem. The question is do you think think this is something that is generically applicable. Would any average user have a use for this?

I don’t use color lights so I’m not a good judge of that. It doesn’t hurt to turn it into a template and see if users come.

This rule is a good candidate because it doesn’t depend on “global” variables.

So what would be the properties? The name of the Group that triggers the rule obviously. I’m thinking the “_RED”, “_GREEN”, and “_BLUE” should be too so users can use names in their own languages.

I think there is a bug here though. If all members of ColourPickers are Color Items, if(triggeringItem.state.toString == "ON") and the “OFF” condition too will never be true. A Color Item’s state is an HSBType whose toString is “H,S,V”, not “ON” or “OFF”. Also, do you really care what the current state of the triggeringItem is or do you mainly care about the command you received? Note that it might be the case that the Item hasn’t changed state in response to the command yet when the rule is running.

Maybe changed is a better choice for a trigger. Then the rule will only run when the Color Item actually changes state.

Another question to consider is whether this overall would be more generically useful. For example, maybe we can create a “Distribute” or “Simple Parser” rule that takes in any Item, splits it on some delimiter, then passes each value out to a number of Items. Then it can be used to parse simple strings of stuff (e.g. from the HTTP binding or MQTT or the like) in addition to these HSBTypes and update or command some Items with each individual part.

The tricky part is how to specify the Items that get the parts. It would be best if the names can be arbitrary if I can figure out a way.

See Colour temp to HSB conversion?

That rule is probably simple enough to not be a template. Installing the template is going to be about as much work as writing the rule itself. Though I could be wrong.

Yeah, I think so.

There is a project going in soon where the customer has bought enough ELV dimmers to drive 36 X RGBW LED strips.

I wrote this rule to get them started.

That was my thinking.

I’ve got it working with 2 x RGBW fixtures in my own home, using the Items shown above.

I think I put this in for the sake of Alexa, I’m fairly sure that I saw Alexa sending an ON command at some point. (I could be wrong)

Again, a very valid point.

In theory, we don’t care what state the target items are in and only want to pass the RGB components.

That’s certainly something I’ve done in Node-RED, within a Function node.

It would have been better to be able to do it in a Rule, as I experienced an issue with timing the commands back to OH3.

(The Colourpicker to RGB solution in Node-RED works really well, but not all the RGB commands would get back to OH3. Hence this rule)

I think I know what you mean.

I found it easy to suffix the name of the triggeringItem with each component.
As you say, not every language calls Red, red.

Yeah, it’s never as simple as it looks.
(Unless I’m missing something really obvious)

It’s the White value of a HSL, rather than just the Brightness / Luminance.

For example, a good Pink, would be White with a hint of Red.

There must be a way, because if the L valve is greater than 50 (in the HabPanel widget, the colour picker colours get “washed out”, which must be the White value.

Yes, maybe just a mention in the “how-to” for the RGB rule would be enough.
(Learning is always better than copying)

Oh, you can absolutely send an ON/OFF command to a Color Item. But you are not checking the command. You are checking the state and a Color Item can’t have an ON/OFF state, only an HSBState.

OK, in that case you want to keep it as received command but then everywhere you’ve got triggeringItem.state needs to be replaced with receivedCommand. That will fix the two if statements too.

And that may be the way it needs to be implemented as a template. However, when writing a template remember you are writing for all openHAB users, not just yourself. Providing the greatest degree of flexibility with the minimum amount of complexity is the goal.

Allowing the users to simply select the Items to use instead of forcing a naming scheme on them helps achieve that goal. It also makes it explicit to them what Items are used by the rule instead of depending on “naming magic”.

Right, hence that link to a post that has two links to external sites that talk about how to convert the HSB to RGB and then convert that to °K. You’d probably then need to further convert that to a percent to send to your Dimmer.