Startup rules 'file not found' workaround

As per this old thread - Those of us still with OpenHAB version 1.x may know that rules files can fail to load at system startup. The larger the file, the more .rules files you have, and the host system performance all seem to play a part. Not likely to get fixed now for OH1

@Marty56 gives us a workaround method there. I have just reworked that a bit to automate the process some. This is for Windows users, *nix folk would have to modify the batch file part.

Create one small batch file, call it rulestouch.bat
This just updates the timestamp on the file. Later on, when OpenHAB notices the update, it will load the file anew.
For simplicity put it in your OpenHAB rules folder.
You may need to edit the path to your rules folder.

IF x%1x==xx GOTO No1
copy /b C:\openhab\configurations\rules\%1.rules +,, C:\openhab\configurations\rules\%1.rules
GOTO End1
:No1
  ECHO No param 1
:End1

In any one of your .items files, create some new Items - one for each of your existing rules files.
Add a new group to include all these.
Be sure you don’t duplicate names with any of your existing Items !

/* kludge for rules load checks */
Group:Switch:AND(ON,OFF) gRules
Switch rulesLoaded "reload flag"
/* here put switch items with names to match files (without the .rules extension) */
Switch doors "doors.rules file [%s]" (gRules)
Switch general "general.rules file [%s]" (gRules)
Switch lights "lights.rules file [%s]" (gRules)

Now make a NEW rules file, call it aachecker.rules
The idea is being small and named starting with ‘a’ it should always load first and successfully.

// This is a kludge to overcome a system limitation
// where during system startup some rules files may fail to load

import org.joda.time.*
import java.util.Map

rule "trigger rules check"
	when
		System started
	then
		createTimer(now.plusSeconds(90)) [ |
			rulesLoaded.sendCommand(OFF)    // trigger main rule
		]
end

rule "do check rules load"
	when
		Item rulesLoaded received command OFF
	then
				// first make a variable that can be passed between lambdas
		val Map<String, String> flagMap = newHashMap
		flagMap.put("flag","OK") // tentative clear flag
 
		gRules.members.forEach[item |
		    var String filename = item.name
			logInfo("rules", "Load checking " + filename + ".rules") 
			if (item.state == Undefined || item.state == Uninitialized) {
				flagMap.put("flag","broke")
				executeCommandLine("C:\\openhab\\configurations\\rules\\rulestouch.bat " + filename)
				Thread::sleep(20000)   // give time to load
			}
		]
		if(flagMap.get("flag") != "OK") {
			createTimer(now.plusSeconds(20)) [ |
				rulesLoaded.sendCommand(OFF)   // repeat in a while
			]
		} else {
			rulesLoaded.sendCommand(ON)   // possible trigger for other rules
		}
end

This rule operates on the Item group, saving having to list all the individual items here.

There remains one tedious job, adding a new rule to the end of each existing rule file to confirm that it was fully loaded.
In this example, we would add to the end of doors.rules -

// kludge to indicate this file loaded ok
rule "doors.rules startup "
	when
		System started
	then
		doors.sendCommand(ON)
end

Make sure that you get all the names matching - the item, and in the rule of each file you want checked.

You may need to alter delay times for best effects, depending on your system

I found I had to go to this trouble when migrating to more powerful server box, and a large rules file failed at every load.

Thanks to Martin for his original work :smile:

EDIT - slightly reworked the code for more consistent use of Item now renamed rules_Loaded.
Other start up rules could be triggered from it more reliably, or its state examined within rules.

2 Likes