[SOLVED] Is it possible to write some Java functions in rules

Hi,
A little beginner (Openhab beginner, and java noob too :smile:) question : Is it possible to write functions in rules. For example, I need to read data in some file. I saw a sample code to do that and I want to use it several times in the same rule

rule "name"
when Some_expression
then
     function read_file(filename) {
        val fileReader = new java.io.FileReader(filename)
	var String line = ""
	var String nextline = ""
	try {
		val values = new java.io.BufferedReader(fileReader)
		nextline = values.readLine
		while (nextline !== null) {
			line += nextline
			nextline = values.readLine
		}	
                return line	
	}	
	finally {
		try { fileReader.close() } catch (Exception e) {}
	}
    }

    // Call the function
    var data = read_file("/path/to/file/data.json")
    ...
    var otherData = read_file("/path/to/file/otherData.json")
    ...
end

You could 1) use a lambda, 2) use executeCommandLine to call any type of script that you can run from command line, 3) use Jython, Groovy or JS with the new rule engine.

There are easier ways to read a file from Rules as well. If you are on Linux or Mac. If you are on Windows replace cat with type.

String data = executeCommandLine("cat /path/to/file/data.json", 1000)
String otherData = executeCommandLine("cat /path/to/file/otherData.json", 1000)

Then you don’t even need the function.

Obviously this only works with text files.

In addition to the options mentioned by Scott, you can

  1. use a separate Rule and store the file contents into a String Item (Design Pattern: Separation of Behaviors)
  2. use an external script to push the contents of these files to OH over the REST API to String Items using curl. You can set up a file watcher to trigger when the files change, or a cron job to run periodically.
  3. if these files don’t change, you can load them in a System started Rule into a String Item or global variable the one time.
1 Like

I don’t think that works. type in windows is not a program, so it can’t be executed.
You’d have to call the command shell instead.

Thanks @rlkoshak for this explanation.
I have tried the execCommandLine solution, but I got an error :

2019-02-07 10:25:00.009 [INFO ] [org.eclipse.smarthome.model.script. ] - Entering Loading_Plannings rule

2019-02-07 10:25:00.065 [ERROR] [ntime.internal.engine.ExecuteRuleJob] - Error during the execution of rule 'Loading_Plannings': An error occurred during the script execution: Couldn't invoke 'assignValueTo' for feature JvmVoid:  (eProxyURI: system.rules#|::0.2.0.2.0.2::0::/1)

However I have the Exec Transformation Add-on installed (but I guess this is only for Items definitions). I also read in the doc that I needed to replace spaces by @@, and of course my json file exists, but nothing better, I still have this error.
Here is my test rule. It is firing every 30 seconds just for testing purpose :

rule "Loading_Plannings"
when  // Seconds, Minutes, Hours, Day-of-Month, Month, Day-of-Week, Year (optional field) 
    Time cron "0,30 * * ? * *"  //System started 
then
    logInfo("", "Entering Loading_Plannings rule")
    String data = executeCommandLine("cat@@/etc/openhab2/data/salles.json", 1000)
    logInfo("", data)
end

I don’t know what I am doing wrong ?

    var String data = executeCommandLine("cat@@/etc/openhab2/data/salles.json", 1000)

or just

    var data = executeCommandLine("cat@@/etc/openhab2/data/salles.json", 1000)

Okayyy my bad :no_mouth:
I did’nt saw this mistake :smile:
This is working fine now.