Filebased rules in one file?

Hi guys,
I’m want to work with file based JS rules. I’m not sure if this is a best practice to manage several rule inside one file. And can I use a variable for the rule name like I do it in this example or can that cause any issues?

garagedoor.js

// ############################# Garagedoor_StatusCalc
var RuleName = RuleName;
let logger = log(RuleName);
rules.JSRule({
    name: RuleName,
    description: "Rule to calculate the open/close status of the garage door in percentage",
    triggers: [triggers.ItemStateChangeTrigger('GA_Garagentormotor_Tor_Fahrt', 'CLOSED', 'OPEN')],
    execute: (event) => {
    ............
    },
    tags: ["GarageDoor", "JS"],
    id: RuleName
  }); 

  // ############################# Garagedoor_CloseStatus
RuleName = "Garagedoor_StatusFinish";
logger = log(RuleName);
rules.JSRule({
    name: RuleName,
    description: "Rule to set Status item to 0 or 100 if door confirms end status",
    triggers: [triggers.ItemStateChangeTrigger('GA_Garagentormotor_Tor_Geschlossen', 'CLOSED', 'OPEN'), triggers.ItemStateChangeTrigger('GA_Garagentormotor_Tor_Offen', 'CLOSED', 'OPEN')],
    execute: (event) => {
      .................
    },
    tags: ["GarageDoor", "JS"],
    id: RuleName
  }); 

I usually put multiple related rules in one file. I have done this with rulesdsl and jruby.

It’s fine to put multiple rules inside one file.

However, your use of the RuleName and logger variables is not going to work like you expect. After the file is loaded and executed, all of your rules will end up with a logger named the same as the ID of your last rule in the file. Each rule doesn’t get its own copy of those “global” variables. They are all using the same variable. They are all pointing to the same place in memory.

If you want a unique logger per rule, you need to create a separate variable per rule, or better yet, define the logger inside the script action of the Rule.

Note, if you leave the default setting for the add-on set to automatically inject the library, I believe you should have a ruleUID variable you can use inside your script action to create the logger. I know you can do this in UI rule script actions but it’s not always clear what’s different between UI and text based rules in these cases.

1 Like

So if I understood you right, I have done the following:

  • moved the logger variable definition into the execute
  • removed the ID
    and so I get completely rid off the RuleName variable
  // ############################# Garagedoor_CloseStatus
logger = log(RuleName);
rules.JSRule({
    name: "Garagedoor_StatusFinish",
    description: "Rule to set Status item to 0 or 100 if door confirms end status",
    triggers: [triggers.ItemStateChangeTrigger('GA_Garagentormotor_Tor_Geschlossen', 'CLOSED', 'OPEN'), triggers.ItemStateChangeTrigger('GA_Garagentormotor_Tor_Offen', 'CLOSED', 'OPEN')],
    execute: (event) => {
      let logger = log("Garagedoor_StatusFinished");
    },
    tags: ["GarageDoor", "JS"]
  }); 

I’m not sure this is right. You still need an ID for your rule or else you’ll get a randomly generated one which complicates some things. And you are still using the RuleName variable to create the logger outside of the rule.

Something like this might work under some circumstances:

rules.JSRule({
    name: "Garagedoor_StatusFinish",
    description: "Rule to set Status item to 0 or 100 if door confirms end status",
    triggers: [triggers.ItemStateChangeTrigger('GA_Garagentormotor_Tor_Geschlossen', 'CLOSED', 'OPEN'), triggers.ItemStateChangeTrigger('GA_Garagentormotor_Tor_Offen', 'CLOSED', 'OPEN')],
    execute: (event) => {
      let logger = log(ruleUID);
    },
    tags: ["GarageDoor", "JS"]
    id: "Garagedoor_StatusFinished"
  }); 

If not than …

rules.JSRule({
    name: "Garagedoor_StatusFinish",
    description: "Rule to set Status item to 0 or 100 if door confirms end status",
    triggers: [triggers.ItemStateChangeTrigger('GA_Garagentormotor_Tor_Geschlossen', 'CLOSED', 'OPEN'), triggers.ItemStateChangeTrigger('GA_Garagentormotor_Tor_Offen', 'CLOSED', 'OPEN')],
    execute: (event) => {
      let logger = log("Garagedoor_StatusFinished");
    },
    tags: ["GarageDoor", "JS"]
    id: "Garagedoor_StatusFinished"
  }); 

Rule UID seems not to work for me.
But it’s not a big thing, then I will copy the text to this line, too.
Just thought, that there is a smart solution :slight_smile:

Failed to execute rule TESTRULE: ReferenceError: "ruleUID" is not defined: ReferenceError: "ruleUID" is not defined