[SOLVED] Jython / JSR223 - Getting UID from a rule

I am using jython to create some advanced handling of my light. It is working fine as, but due to various changes in the jsr223 I had made some panic changes / hacks over time. And I am quite sure that it could be simplified a lot.
I would like to have the ability to enable / disable rules by thier UID. I have found quite a few examples of that. But the problem is that UID always return None for the class. The rule triggers will be created dynamically. I was first looking at the decorator approach, but I cannot figure out how to build multiple instances of a decorated class. Therefore I continued to look at this approach:

scriptExtension.importPreset("RuleSupport")
scriptExtension.importPreset("RuleSimple")

class MyRule(SimpleRule):
    def __init__(self):
        self.triggers = [
            TriggerBuilder.create()
                    .withId("MyTrigger")
                    .withTypeUID("core.ItemStateUpdateTrigger")
                    .withConfiguration(
                        Configuration({
                            "itemName": "TestString1"
                        })).build()
        ]
        
    def execute(self, module, input):
        events.postUpdate("TestString2", "some data")

my_rule = MyRule()
automationManager.addRule(my_rule)

If I query the UID, I just get nothing back.

I also tried this approach (with same result):

from org.slf4j import LoggerFactory

scriptExtension.importPreset("RuleSupport")
scriptExtension.importPreset("RuleSimple")

class GenericCronTriggerRawAPI(SimpleRule):
    def __init__(self):
        self.triggers = [
            TriggerBuilder.create()
                    .withId("Hello_World_Cron_Trigger")
                    .withTypeUID("timer.GenericCronTrigger")
                    .withConfiguration(
                        Configuration({
                            "cronExpression": "0/10 * * * * ?"
                        })).build(),
            TriggerBuilder.create()
                    .withId("Hello_World_Item_State_Trigger")
                    .withTypeUID("timer.GenericCronTrigger")
                    .withConfiguration(
                        Configuration({
                            "itemName": "Test_Switch_1"
                        })).build()
        ]
        self.name = "Jython Hello World (GenericCronTrigger raw API)"
        self.description = "This is an example Jython cron rule using the raw API"
        self.tags = set("Example rule tag")
        self.log = LoggerFactory.getLogger("jsr223.jython.Hello World (GenericCronTrigger raw API)")

    def execute(self, module, inputs):
        self.log.info("Hello World!")

automationManager.addRule(GenericCronTriggerRawAPI())

The above samples is from the documentation and I have tried on my Windows machine until now. Any suggestions?

I can confirm the same behaviour on my ubuntu box (openHAB 2.5.0M4) and my Windows box running latest snapshot.

I think I have found the solution on how to get the UID. By looking into the jython code of the helper library. I found some code that was using the addRule method in the library instead of calling the Java equivalient. Allthough this is not my problem, it is a much better approach, because it deals with the change in name space. The problem is that I did something like this:

myRule1 = MyRule()
addRule(myRule1)

myRule2 = MyRule()
addRule(myRule2)

The above doesn’t give any UID. Both If I remeber to assign the result of addRule to something, then I have access to the UID:

myRule1 = MyRule()
newRule1 = addRule(myRule1)

myRule2 = MyRule()
newRule2 = addRule(myRule2)

Both newRule1 and newRule2 has a valid UID.

It looks like you got this sorted out, but I’m curious what you mean about this…

Here is an example using the decorators…

from core.rules import rule
from core.triggers import when

@rule("Test rule 1")
@when("Time cron 0/5 * * * * ?")
def test_rule_1(event):
    test_rule_1.log.info("Test rule 1 has executed")

@rule("Test rule 2")
@when("Time cron 0/30 * * * * ?")
def test_rule_2(event):
    from core.osgi import get_service
    rule_manager = get_service("org.openhab.core.automation.RuleManager") or get_service("org.eclipse.smarthome.automation.RuleManager")
    if rule_manager.isEnabled(test_rule_1.UID):
        rule_manager.setEnabled(test_rule_1.UID, False)# disable rule
        test_rule_2.log.info("Test rule 1 was enabled but is now disabled")
    else:
        rule_manager.setEnabled(test_rule_1.UID, True)# enable rule
        test_rule_2.log.info("Test rule 1 was disabled but is now enabled")

https://openhab-scripters.github.io/openhab-helper-libraries/Guides/But%20How%20Do%20I.html#get-the-uid-of-a-rule-by-name

I saw the sample, and the decorator approach looks cool. But for my use I would prefer having a class instance, this will avoid to much rework :slight_smile:

OK… you mean rework to rewrite your rules… I was thinking you might be meaning that the decorators are lacking in functionality that you need. BTW, the rule decorator will also add a UID property to a decorated class, if you only want to use the extensions.

1 Like