That’s correct. Libraries need to go into the automation/lib/python
set of folders. automation/lib/python/personal
is where you normally put your own libraries. Then you need to import them the functions/classes into your rule’s .py files like any other library, e.g. the Helper Libraries.
The terminology is “scripts” and “modules”. “Scripts” are rules and go in automation/jsr223/python
. Modules are libraries and go in automation/lib/python
. Modules can not be executed on their own. They must be imported into a script and run from a script.
You cannot put a Rule into a module (with some caveats because you can create rules from a library function, but it takes a script to load and execute that module).
What is the concern about putting those functions into a module? That is how it’s supposed to work after all. Common code like that is usually put into a module so it can be used across your scripts. If it’s just about having access to events
you can:
- pass
events
as an argument to the function - import events by including the following at the top of your module
from core.jsr223.scope import events
Other alternative approaches:
- Put all the rules that depend on that function into the same .py file and declare the function in that file.
- Send a command to an Item that triggers a rule that does the task (see Design Pattern: Separation of Behaviors)
- Trigger the rule to run directly. As an example here is how to trigger a rule from another rule (sorry it’s in JavaScript but it’s dealing with openHAB core Java Objects so the should be roughly the same.
// Run another rule
var FrameworkUtil = Java.type("org.osgi.framework.FrameworkUtil");
var _bundle = FrameworkUtil.getBundle(scriptExtension.class);
var bundle_context = _bundle.getBundleContext()
var classname = "org.openhab.core.automation.RuleManager"
var RuleManager_Ref = bundle_context.getServiceReference(classname);
var RuleManager = bundle_context.getService(RuleManager_Ref);
RuleManager.runNow("tocall");
var map = new java.util.HashMap();
map.put("test_data", "Passed data to called function!")
RuleManager.runNow("tocall", true, map); // second argument is whether to consider the conditions, third is a Map<String, Object> (way to pass data)
But you need to know or search for the rule ID ahead of time. And if I recall the UIDs for .py rules are randomly generated. So you’ll have to tag the rule and search the RuleRegistry for the right UID.
But for what you have described, the best approach is to use a module. That’s what they are there for.