[SOLVED] Rules: only primitive types working in Variable Declaration Section

I can only get primitive variables to work in the Variable Declaration section of my rules file, not Objects (or at least not the Object I’m trying to use, which is an Item). The specific statement looks like this:

val SUNRISE_DIMMER = Hue_test_1

Yet, if I put that same statement in the “then” clause of a rule, it works as expected, although it’s only visible to that particular rule, and I wanted something visible to all rules in the file.

The specific error in the log file is:

Cannot reference the field 'Hue_test_1' before it is defined

Although that doesn’t make sense, because why would it be defined within the “then” clause, but not at the top of the file?

Any suggestions?

Unless that changed very recently, DSL has a structured approach to the scope of variable declarations.

  • variables declared at the top of the rules file (and outside a rules block) are global for that specific rules file
  • As you found out already, variables declared within a rule extend only to this rule
  • and I believe that DSL continues this approach: a declaration within a code block of a rule restricts the scope to this code block
  • There is NO possibility (that I am aware of) in rules DSL to have a truly global variable the scope of which extends over all rule files.

From My experience you can ignore the warning, it works anyway. I used a hashmap to map an item to a String that was used to communicate with an external script. I got the same warning, but when the rule was executed it worked anyway.

But I have to ask: why would you want to have a single item in a variable? All items are globally available to all rules anyway.

No, I don’t want the variable available to all rule files, just all the rules in a single file.

@dmclane just put the variable declaration at the beginning of your rules file

1 Like

Duh, you’re right, It works, despite the warning in the logs. Yes, I thought it was an error, so I never even tried the rule. Not the dumbest thing I’ve done in my life, but the dumbest thing I’ve done this week.

Thank you, I was stuck. Now I’m moving again.

Why? Well, one reason is to test the rule with one item, but ultimately use a different item. The other reason is that I gave some items some names that weren’t very meaningful (you know, names like “test_1”). If you have to change a variable name is several places, odds are good you’ll miss one of those places.

Based on my experience this may not work long term. For awhile I was using the Item object itself as the key to a HashMap of Timers and after awhile I couldn’t pull the Timers out with the Item any more. The problem is that every time the Rule runs the Item Object gets recreated for the Items used in the Rule. Because of that the Hash function returns a different value and thus no longer can be used to pull the value out of the Map. I’ve also found that the Item gets stale and calls to MyItem.sendCommand stop working over time.

Maybe this is something has been fixed. But using the Item’s name as the key works much better and will continue to work in case this is still a problem or becomes a problem again.

This is definitely an anti-pattern. Your Items are the logical model for your home automation. They should ALL have meaningful names and names that are meaningful in relation to how it is used. Zwave_Node12 is a horrible Item name. LivingRoom_Lamp is a better Item name. It says what it is and what it’s used for.

You would be far better off fixing the names of your Items instead of patching over the problem using variables. This is what they call in software development “technical debt”. You eventually the “loan” comes due and it almost always ends up costing way more than you expect.

Rules are the most complex part of your OH setup. If you can move any of that complexity out of the Rules and into Items, or Things, or Persistence then you should do that. It will lower the overall complexity of your OH system. See Design Pattern: DRY, How Not to Repeat Yourself in Rules DSL for other techniques you can use to simplify your Rules logic.

grep variableName myrules.rules

returns all places where the variableName exists.

VSCode and other editors have find and replace.

Fear of missing a change to a variable name is a poor excuse to using proper Item names. I cannot stress the importance of this enough.