Global variables in OpenHAB and non-repetitive rules

Hi, I’m trying to figure out how to write an effective and non-repetitive rules. This is what I want to accomplish:

To have one HABPanel with several sitemaps, all functioning at the same time, with the “same” buttons, e. g. the buttons all will have the same function, but will be different objects (items). Values for them will be different, but in fact will all be doing the same thing.

For example I will have Feeder 1, Feeder 2 and Feeder 3 for different rooms (that’s just an “stupid” example, I don’t really want to write details of my project). Feeder1 sitemaps’ buttons will trigger some rules, scripts and so on. Feeder2 and 3 buttons will do the same thing, only change will be the number in the buttons’ names, like for Feeder1 i will have FeedTheCat1, FeedTheDog1, for Feeder2 FeedTheCat2… You get the idea.

I know I have to actually create all the buttons by myself. I have rules working for sitemap1 and I could easily rewrite it for all of them, changing the numbers, but that seems just stupid and I don’t want to write nasty codes.

rule “Feed the cat 1”
when
Item FeedTheCat1 was changed to ON
then
val command = "python3 /etc/openhab2/feeder/feedthecat.py 1 "

Maybe some version of

rule “Feed the cats”
when Group’s FeedTheCats Item changed
then
val number = parse the triggered buttons name and get the last character in it
val command = "python3 /etc/openhab2/feeder/feedthecat.py " + number

I have read through the Design Pattern: Working with Groups in Rules article, but the thing is, all of the buttons can be triggered at any time and don’t depend on each other trhough the sitemaps, but are related in one - e.g. pushing one button will set values to others, execute scripts and so on.

Please ignore the syntax, I just want the correct idea. In another programming language that would be a piece of cake for me (simple function with arguments), but I’m not really familiar with OpenHAB concept yet.

I know you can trigger a rule when any of the group’s button was changed, but how to determine which one of it was it without writing milions of if’s? What if they get triggered at the same time?

I don’t want you to write the code for me, I’m just thinking of the best solution and would appreciate any push (or a kick, really :D), if you are willing to share your ideas with me.

See Design Pattern: Associated Items for some inspiration. The easiest thing to do would be to put some sort of separator between the main part of the Item name and the number. Then you can split on that character and grab the last part. If the Item name is FeedTheCat_1 in the rule you can

val number = triggeringItem.name.split('_').get(1)

OH supports Jython, JavaScript, and Groovy as options. But you are still dealing with the Item name that triggers the rule.

See https://www.openhab.org/docs/configuration/rules-dsl.html#implicit-variables-inside-the-execution-block

In Rules DSL in OH 2.5, two copies of the rule will be running at the same time. In OH 3 or the other languages the triggers will be queued and run in FIFO.

Another approach, since you are just building is a command line, is to have just the one Item and configure to send the number as the command. Then you can use the Exec binding and link the input Channel to that Item and you don’t even need rules at all.

Thank you for your time, I’ll dig into it and post here, if I’ll be succesfull. The command is just a small part of the rule, I have to do other stuff with the button number.

If you want to create rules in python3, you can also try HABApp.
Rules are just class instances, so it’s easy to create them with different parameters.

With your help now I have a functioning model.

I grouped all of my items and created similar names for them, something like

Group FEEDER_StartButtons
String StartButtonFEEDER_0 “FEEDER 0 Start Button” (FEEDER_StartButtons)
String StartButtonFEEDER_1 “FEEDER 1 Start Button” (FEEDER_StartButtons)
String StartButtonFEEDER_15 “FEEDER 15 Start Button” (FEEDER_StartButtons)

Rule example:

import org.eclipse.smarthome.model.script.ScriptServiceUtil

    rule "Start Feeder"
    when
        Member of FEEDER_StartButtons received command ON
    then
        val number = triggeringItem.name.split('_').get(1)
        val command = "python3 /etc/openhab2/myscript.py " + number + " "
        val duration = ScriptServiceUtil.getItemRegistry.getItem("ParamDurationFEEDER_" + number)
   val frequency = ScriptServiceUtil.getItemRegistry.getItem("ParamFrequencyFEEDER_" + number)
   if( duration.state == 0 || duration.state == NULL ) postUpdate(duration, 1)
   command += duration.state.toString + " " + frequency.state.toString 
   postUpdate(triggeringItem, "OFF")
   val results = executeCommandLine(command)
end

In fact the rules are little more complicated, but maybe this can help someone. For me the important thing I couldn’t find for some time was how to dynamically convert string into variable

val duration = ScriptServiceUtil.getItemRegistry.getItem(“ParamDurationFEEDER_” + number)

Then you can do various stuff with said object.

Again, thanks for help.

When you have the Item, use the method for postUpdate and sendCommand instead of the action. For more details see https://www.openhab.org/docs/configuration/rules-dsl.html#myitem-sendcommand-new-state-versus-sendcommand-myitem-new-state

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