This works but has another missleading thing. I must define the absolute path to the configFile. This is not generic and i have not find a way to use a relative path to the OH conf folder.
So, two questions:
Is there a way to avoid the caching from require?
Is there a way to use realtive paths when using the java class?
No I don’t think so, but you can wipe the cached “module” from the object that tracks the caching. I assume this works in text-based rules. Something like
delete require.cache['../configFile.js']
You might need the full path, I don’t know if the cache keys use the relative paths or resolve them to the full path name.
Put that before your declaration and require will reload the file every time. But, unless this file of yours changes very frequently, I would think it would be less of an issue to just reload the rules file occasionally than to read that config file every single time the rule runs.
A third way is to use executeCommandLine and cat to read in a text file. Yes a quick one liner and you don’t need to mess with Java io.
But if this “config” changes frequently you should consider whether some of the values should be Items so they can be more easily changed through the UI instead of editing a text file on the host.
I’m sure you could use a restrictive path, but the path is going to be relative to the directory OH started in which is likely /var/lib/openHAB (which corresponds to the openhab 's home directly) or it might be /etc/openHAB.
And a fourth way is to create your own node module that includes that config file. When node modules are changed, all depending rules and scripts are reloaded to pick up that change.
Have a look at the JS Scripting README to see how to create a node module.
For my usecases i would see some pro’s and con’s.
One usecase is the timeline picker and here there are more users with differnet OS. So i’m looking for a ‘robust’ solution.
Pro: pure js
con: it dosen`t work (see below)
pro: short
con: it’s not portable, windows dosen’t know cat
pro: All my rules in one place in this module
con: I think the folder node_modules is not the right place for configs
I tried delete require.cache['../test-function.js'] with relative and absolute path.
Unfortunaly i get the following error message. The relative path as key nor the absolute path as key changing this behavior.
2023-05-13 12:24:24.192 [ERROR] [b.automation.script.javascript.stack] - Failed to execute script:
org.graalvm.polyglot.PolyglotException: TypeError: Cannot delete property "/etc/openhab/automation/js/test-function.js" of undefined
at <js>.:program(Unknown) ~[?:?]
at org.graalvm.polyglot.Context.eval(Context.java:399) ~[?:?]
at com.oracle.truffle.js.scriptengine.GraalJSScriptEngine.eval(GraalJSScriptEngine.java:458) ~[?:?]
at com.oracle.truffle.js.scriptengine.GraalJSScriptEngine.eval(GraalJSScriptEngine.java:400) ~[?:?]
at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:249) ~[java.scripting:?]
at org.openhab.automation.jsscripting.internal.scriptengine.DelegatingScriptEngineWithInvocableAndAutocloseable.eval(DelegatingScriptEngineWithInvocableAndAutocloseable.java:58) ~[?:?]
at org.openhab.automation.jsscripting.internal.scriptengine.InvocationInterceptingScriptEngineWithInvocableAndAutoCloseable.eval(InvocationInterceptingScriptEngineWithInvocableAndAutoCloseable.java:84) ~[?:?]
at org.openhab.automation.jsscripting.internal.scriptengine.DelegatingScriptEngineWithInvocableAndAutocloseable.eval(DelegatingScriptEngineWithInvocableAndAutocloseable.java:58) ~[?:?]
at org.openhab.automation.jsscripting.internal.scriptengine.InvocationInterceptingScriptEngineWithInvocableAndAutoCloseable.eval(InvocationInterceptingScriptEngineWithInvocableAndAutoCloseable.java:84) ~[?:?]
at org.openhab.core.automation.module.script.internal.ScriptEngineManagerImpl.loadScript(ScriptEngineManagerImpl.java:185) ~[?:?]
at org.openhab.core.automation.module.script.rulesupport.loader.AbstractScriptFileWatcher.createAndLoad(AbstractScriptFileWatcher.java:276) ~[?:?]
at org.openhab.automation.jsscripting.internal.fs.watch.JSScriptFileWatcher.createAndLoad(JSScriptFileWatcher.java:63) ~[?:?]
at org.openhab.core.automation.module.script.rulesupport.loader.AbstractScriptFileWatcher.importFile(AbstractScriptFileWatcher.java:256) ~[?:?]
at org.openhab.core.automation.module.script.rulesupport.loader.AbstractScriptFileWatcher.lambda$5(AbstractScriptFileWatcher.java:248) ~[?:?]
at java.util.Optional.ifPresent(Optional.java:183) ~[?:?]
at org.openhab.core.automation.module.script.rulesupport.loader.AbstractScriptFileWatcher.importFileWhenReady(AbstractScriptFileWatcher.java:246) ~[?:?]
at java.lang.Iterable.forEach(Iterable.java:75) ~[?:?]
at org.openhab.core.automation.module.script.rulesupport.loader.AbstractScriptFileWatcher.processWatchEvent(AbstractScriptFileWatcher.java:223) ~[?:?]
at org.openhab.automation.jsscripting.internal.fs.watch.JSScriptFileWatcher.processWatchEvent(JSScriptFileWatcher.java:56) ~[?:?]
at org.openhab.core.service.WatchQueueReader.lambda$5(WatchQueueReader.java:357) ~[?:?]
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515) [?:?]
at java.util.concurrent.FutureTask.run(FutureTask.java:264) [?:?]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304) [?:?]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) [?:?]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) [?:?]
at java.lang.Thread.run(Thread.java:829) [?:?]
2023-05-13 12:24:24.202 [ERROR] [ipt.internal.ScriptEngineManagerImpl] - Error during evaluation of script 'file:/etc/openhab/automation/js/test-require.js': org.graalvm.polyglot.PolyglotException: TypeError: Cannot delete property "/etc/openhab/automation/js/test-function.js" of undefined
The require object exist and i can write this to the log:
JS Scripting does not provide a real NodeJS environment. The JS Scripting provides a require, but it is implemented in the Java layer of the binding and I guess doesn’t behave like the original require in all aspects.
I would like to add a fifth way:
Create one script that puts your configuration in the shared cache. This allows you to access your configuration from any script in any language supported in openHAB.
If you update your conf script, the shared cache entry will be updated and the next time your rules are run they will use the new conf because they get the conf from the shared script every time.