Port JSR223 bundle to openHAB 2

I have setup
-Dpython.path=c:/Progs/Openhab2/conf/automation/lib
and put different libraries in the lib folder.

in the \jsr223\ - folder I have two files and in both I do an
import testModule
Library seems to be loaded twice and does not share any variables between instances.
This seems to be a very odd behavior. How do I properly share the module?

In the library-file I do:

import testModule

print( 'TESTPROP: {}'.format(hasattr(testModule, 'TESTPROP')))
testModule.TESTPROP = 'TEST'
print( 'TESTPROP: {}'.format(hasattr(testModule, 'TESTPROP')))

results in:

Loading testModule
TESTPROP: 0
TESTPROP: 1
Loaded testModule

Loading testModule
TESTPROP: 0
TESTPROP: 1
Loaded testModule

I have created a small zip with which one can reproduce the problem.
It contains all files and can be downloaded here

Please share! Also, include your OH version because I this area of the code has been/is being refactored. With a recent snapshot build, I can get the UID, but havenā€™t tried enable/disable/remove.

I did edit my response :slight_smile: . Can you reproduce the import problem?
I am running 2.3 stable.

@steve1:
Would you be so kind and take a look, too?

Iā€™m on vacation so I canā€™t try out the code. Just looking at it though, my guess is the issue is related to circular dependency between the testModule package (which imports the test_file module) and the test_file module (which imports the testModule package). Jython might not handle this scenario gracefully.

Thanks for the hint.
I did modify the test_file so it doesnā€™t import the module anymore (instead I load it from sys.modules).

import sys
this_module = sys.modules[__name__.split('.')[0]]

print( 'TESTPROP: {}'.format(hasattr(this_module, 'TESTPROP')))
setattr(this_module, 'TESTPROP', 'TEST')
print( 'TESTPROP: {}'.format(hasattr(this_module, 'TESTPROP')))

Unfortunately this does not change the output so something es seems to be off:

Loading testModule
TESTPROP: 0
TESTPROP: 1
Loaded testModule

Loading testModule
TESTPROP: 0
TESTPROP: 1
Loaded testModule

Enjoy your holiday! :sunny:

Edit:
I did some more testing and found that the import issue is related to jython 2.7.1.
Using jython 2.7.0 it works as intended.

Does anybody know what changed with the ruleRegistry? E.g.

ruleRegistry.setEnable(myRuleId, false)

or

ruleRegistry.runNow(myRuleId)

is not working anymore, because the the function was deleted, as can be seen here: Link

How can i reimplement those functions?

Thanks in advance.

Edit: Ok i solved it with the restAPI. My python scripts send a post request via urllib2. When i am home i can share my code if someone is interested

Hey can you share a code example how you set a custom UID to your rule?
Rule Class seems to have a constructor which supports adding a custom UID, but SimpleRule Class seems not.
Do you use SimpleRule? If i pass a string to it, it complains about not expecting an argument.

Thanks :slight_smile:

This was the code:

    from org.eclipse.smarthome.automation import Rule as OpenhabRule
    def set_UID(self, val):
        # set as UUID of Rule
        uid_field = type(OpenhabRule).getClass(OpenhabRule).getDeclaredField(OpenhabRule, "uid")
        uid_field.setAccessible(True)
        uid_field.set(self, val)

Unfortunately this does not work anymore:
java.lang.NoSuchFieldException: java.lang.NoSuchFieldException: uid
Has anyone figured out another way to set the UID?

I poked at this for a bit, but in the end decided it was not worth more effort. It was really the Name and Description fields that were useful for me. I removed the setting of the Rule UID here, since it was throwing the NoSuchFieldException, and plan to change the logging to include the Rule Name to make the logs more readable. Your post reminded me of the logging, which Iā€™d completely forgotten about!

@5iver:
Is the StartupTrigger for you working? With the latest snapshot 2.4 I get Missing handler 'jsr223.StartupTrigger':

[.event.RuleStatusInfoEvent] - e28a752f updated: UNINITIALIZED (HANDLER_INITIALIZING_ERROR): Missing handler 'jsr223.StartupTrigger' for module 'StartupTrigger_41e411dee3e211e8ac0a3708d2a63798'

Also the option to disable rules seems to have been removed. Any Idea how to delete a rule?

No. I havenā€™t dug into it since I just launch functions on script startup, rather than using a rule.

The tricky part is getting the uid, which is a string. You could paste them in from Paper UI, or if you know the name of the rule and youā€™ve kept them unique, you can do thisā€¦

scriptExtension.importPreset("RuleSupport")
ruleUID = filter(lambda rule: rule.name == "Alert: TV turn off timer alert", rules.getAll())[0].UID

from openhab import osgi
ruleEngine = osgi.get_service("org.eclipse.smarthome.automation.RuleManager")
ruleEngine.setEnabled(ruleUID, True)# enable rule
ruleEngine.setEnabled(ruleUID, False)# disable rule

Unless Iā€™m mistaken, you should be able to get the ruleā€™s UID by invoking the method getUID() on the object returned by the method addRule(). That UID could then be added as a new attribute of the function object or, perhaps more useful, saved to a module-scope dictionary of rule-name:rule-uid key-value pairs before returning from the rule() decorator.

What I was meaning as tricky was the actual use of them. I was curious how Sebastian was planning to use them.

One use case would be to have a TimeOfDay type rule, and when the ToD changes, you could enable/disable certain rules. For this, Iā€™m thinking of adding a tag to each pertinent rule to group them. Then to perform and action on them, such as enable/disable, you could filter all rules from the registry by a particular tag, and iterate through them to pull out the UID and enable/disable.

Having the UID as a function attribute or in a UID:name dict are good ideas and might be helpful, but Iā€™m not clear on how/if it would be used. I think tagging the rules could be more useful. Having a UI to add/remove rule tags would be really nice. BTWā€¦ in case people havenā€™t noticedā€¦ we can enable/disable Jython rules through PaperUI.

One use that came to mind was as a means of implementing a one-shot trigger rule when the rule UID is saved as an attribute of the callable object known as function in the rule decorator. A one-shot trigger ruleā€™s action could disable the rule as itā€™s final act before returning.

That would be handy! I was thinking it would be cleaner to just include the rule UID in the event object, but I couldnā€™t get that to work. So, I added the rule UID as an attribute of the function. I also added a tags parameter to the rule decorator. Iā€™ve tested them but havenā€™t merged, if youā€™d like to review.

@5iver, thanks for asking me to take a look before you merge your updates ā€“ done.