Is there a limit to how many rules can be in a .rules file?

Hey all, I have come across an issue that doesn’t seem like it should be an issue to me.

I have my rules files orginized in the following way:
All lighting related rules go in lighting.rules
All hvac related rules go in hvac.rules
Irrigation is irrigation.rules
And security is security.rules

The problem I come across is when a rules file starts to get too big, some rules in it will fire for just fine for a while, but then they stop firing and won’t fire until I restart OH, yet they work perfectly when I put them in their own rules files.

I have been able to replicate this on multiple different setups.

My current setup is Openhabian custom install on ubuntu server 16.0.4 LTS OH 2.1

  • Platform information:
    • Hardware: CPUArchitecture/RAM/storage
    • OS: what OS is used and which version
    • Java Runtime Environment: which java platform is used and what version
    • openHAB version:
  • Issue of the topic: please be detailed explaining your issue
  • Please post configurations (if applicable):
    • Items configuration related to the issue
    • Sitemap configuration related to the issue
    • Rules code related to the issue
    • Services configuration related to the issue
  • If logs where generated please post these here using code fences:

Short answer, no, there is no limit.

Please gather as much information you can including debug logs when the rules stop firing, watch the memory usage and CPU, and file an issue on the ESH repo.

How big is too big? I know some users have .rules files that run in the thousands of lines. I personally spend a lot of effort to make sure my rules are short and simple so I’ve not seen anything like this.

Is suppose too big isn’t the right statement here as it varies.
The thing about that is, I am unsure. One file Has a bunch of short simple rules in it. And the rule that quits firing is also very simple.

While on the other hand i have another simple rule in a file with some more complex rules. And the one simple rule quits firing. The only thing Ive been able to do to ensure they always fire is to put them in their own .rules file

I dont have time right now to go through the logs, but I will this evening. The cpu stays around 11% and memory is almost always below 50%

Do you have any Thread::sleep statements or ReentrantLocks?

I don’t have anything with Thread::sleep and I’m not sure what you mean by reentrant locks.

here is my lighting.rules:

////////////////	Garage Lighting	//////////////////
rule "Garage Motion"
	when
		Item GarageMotion received update
	then
		if (grageMotionEnable.state==ON){
			sendCommand(garageMotionBit,ON)
			sendCommand(garageLightsTimer,ON)
			if(GarageOneLights.state==ON)sendCommand(garageMotionBit,OFF)
			if (GarageOneLights.state!=ON)sendCommand(GarageOneLights,ON)	
		}
end
rule "Turn Off Garage Lights"
	when
		Item garageLightsTimer received update OFF
	then
		if(grageMotionEnable.state==ON&&GarageOneLights.state!=OFF)sendCommand(GarageOneLights,OFF)
end
rule "Enable Garage Motion"
	when
 		Item GarageOneLights changed from ON to OFF
 	then
 		if(grageMotionEnable.state!=ON)sendCommand(grageMotionEnable,ON)
end	
rule "Disable Garage Motion 1"
 	when
 		Item GarageOneLights received command ON
 	then
 		if(garageMotionBit.state==OFF)sendCommand(grageMotionEnable,OFF)
 		else (garageMotionBit.state==ON)sendCommand(garageMotionBit,OFF)
end
rule "Disable Garage Motion 2"
	when 
		Item garageLightsFast received command ON
		or
		Item Garage_One_Remoteb2 received command ON
	then
		sendCommand(grageMotionEnable,OFF)
end
////////////// Foyer Keypad /////////////
rule "Foyer Lights - KeypadB"
	when
		Item FoyerLights received update 
	then
		if (FoyerLights.state >= 1 && keypadSwitchB.state != ON)sendCommand(keypadSwitchB,ON)
		else(FoyerLights.state==0 && keypadSwitchB.state != OFF)sendCommand(keypadSwitchB,OFF)
end

rule "Keypad D - LR Lights"
	when
		Item keypadSwitchD changed
	then
		if (keypadSwitchD.state==ON && LRLights.state != 100)sendCommand(LRLights,100)
		if (keypadSwitchD.state==OFF && LRLights.state != 0)sendCommand(LRLights,0)
end
rule "LR Lights - KeypadD"
	when
		Item LRLights received update 
	then
		if (LRLights.state >= 1&& keypadSwitchD.state != ON)sendCommand(keypadSwitchD,ON)
		if (LRLights.state == 0&& keypadSwitchD.state != OFF)sendCommand(keypadSwitchD,OFF)
end

rule "Dinning Lights - KeypadE"
	when
		Item DinningLights received update 
	then
		if (DinningLights.state >= 1&& keypadSwitchE.state != ON)sendCommand(keypadSwitchE,ON)
		if (DinningLights.state == 0&& keypadSwitchE.state != OFF)sendCommand(keypadSwitchE,OFF)
end

rule "Kitchen Lights - KeypadF"
	when
		Item KitchenLights received update 
	then
		if (KitchenLights.state >= 1&& keypadSwitchF.state != ON)sendCommand(keypadSwitchF,ON)
		if (KitchenLights.state == 0&& keypadSwitchF.state != OFF)sendCommand(keypadSwitchF,OFF)
end

rule "Basement Stairwell - KeypadG"
	when
		Item BasementStairwellLights received update 
	then
		if (BasementStairwellLights.state >= 1&& keypadSwitchG.state != ON)sendCommand(keypadSwitchG,ON)
		if (BasementStairwellLights.state == 0&& keypadSwitchG.state != OFF)sendCommand(keypadSwitchG,OFF)
end

and this is the rule that stops firing after a while, I have put it in a separate lighting-1.rules:

///////////jory
rule "Jory lava lamp control"
when
	Item JoryLavaLamps received update
then
	if(JoryLavaLamps.state==100){
		if(JoryLight.state!=0)JoryLight.sendCommand(0)
		if(JoryLamps.state!=20)JoryLamps.sendCommand(20)
		}
	if(JoryLavaLamps.state==0){
		if(JoryLight.state!=0)JoryLight.sendCommand(0)
		if(JoryLamps.state!=0)JoryLamps.sendCommand(0)
		}
end

Just this rule or all rules?

Do you see in events.log that JoryLavaLamps is being updated? Have you added a logging statement to verify whether the Rule is in fact not triggering versus just not doing what you expect?

I’m just trying to rule out some of the things you could do inside your Rules that could cause them to stop responding. Both Thread::sleep and ReentrantLock can tie up an exeuction thread, eventually leaving none left to run your Rules while waiting for the sleeps to end or the locks to be released.

Just this one, I have another rule I have taken out of hvac.rules that has the same behavior here:

rule "Convert broadlink tempC to TempF"
when 
	Item RMProTempC changed
then
	var Number BLtempC =  RMProTempC.state as DecimalType
	var Number BLtempF = (BLtempC * 1.8) + 32
	RMProTempF.postUpdate(BLtempF)
end

I do, every time always see an update from JoryLavaLamps

I Have not, I understand the importance of logging but I haven’t been able to figure out how to implement it (I’m not a very good programmer, I come from writing stuff in C for the arduino, and just pick up bits as I go along)

https://docs.openhab.org/administration/logging.html#create-log-entries-in-rules

OH wow, that is dead simple. Thank you, I will add logging to find out if it fires and report back

I’d code that previous one more more like

rule "Jory lava lamp control"
when
	Item JoryLavaLamps received update
then
	if (JoryLavaLamps.state==100) {
		if(JoryLight.state!=0)JoryLight.sendCommand(0)
		if(JoryLamps.state!=20)JoryLamps.sendCommand(20)
		}
	 else if (JoryLavaLamps.state==0) {
		if(JoryLight.state!=0)JoryLight.sendCommand(0)
		if(JoryLamps.state!=0)JoryLamps.sendCommand(0)
		}
	 else {
		logInfo("OOPS", "was not expecting " + JoryLavaLamps.state)
		}
end

Thanks, I just put :
logInfo(“Lava control Fired”)
Right after then, but I will add your bit it will be interesting to see what comes back.

Thanks again

Edit: I have updated my rule and put it back in the original lighting.rules it reads like this:

rule "Jory lava lamp control"
when
	Item JoryLavaLamps received update
then
	logInfo("LavaControl Fired","level" + JoryLavaLamps.state)
	if(JoryLavaLamps.state==100){
		if(JoryLight.state!=0)JoryLight.sendCommand(0)
		if(JoryLamps.state!=20)JoryLamps.sendCommand(20)
		}
	if(JoryLavaLamps.state==0){
		if(JoryLight.state!=0)JoryLight.sendCommand(0)
		if(JoryLamps.state!=0)JoryLamps.sendCommand(0)
		}
	else {
		logInfo("OOPS", "was not expecting " + JoryLavaLamps.state)
		}
end

Have another look at the if-else structure.
My example was if XX elseif YY else ZZ
Only one of those three conditions can be met (in this case the third is one that we were not really expecting, and is just there in case of errors).
Note that one of the three blocks must always execute.

Your rewrite boils down to
if XX
if YY else ZZ
This is not quite the same, it is possible for none of the code blocks to execute.
Consider what happens if the test is neither XX nor YY. In this case you aren’t expecting that to happen, but the extra “else” part ZZ to warn you about the suprise won’t get executed.

It’s not a big deal, but thinking through “what if” things like this can help avoid unintended behaviour in rules.

Oh sorry didn’t notice that change, The rule has stopped firing again. here is log from around that time:

==> /var/log/openhab2/events.log <==

2018-01-09 07:34:35.054 [vent.ItemStateChangedEvent] - JoryLavaLamps changed from 0 to 100

==> /var/log/openhab2/openhab.log <==

2018-01-09 07:34:36.397 [INFO ] [onplm.internal.device.MessageHandler] - DimmerRequestReplyHandler: set device 27.2A.DC to level 58

==> /var/log/openhab2/events.log <==

2018-01-09 07:34:36.397 [vent.ItemStateChangedEvent] - JoryLavaLamps changed from 100 to 58

==> /var/log/openhab2/openhab.log <==

2018-01-09 07:34:41.305 [INFO ] [onplm.internal.device.MessageHandler] - DimmerRequestReplyHandler: set device 30.B7.04 to level 0

2018-01-09 07:34:45.048 [INFO ] [onplm.internal.device.MessageHandler] - LightOffDimmerHandler: device 27.2A.DC was turned off REGULAR.

==> /var/log/openhab2/events.log <==

2018-01-09 07:34:45.049 [vent.ItemStateChangedEvent] - JoryLavaLamps changed from 58 to 0

==> /var/log/openhab2/openhab.log <==

2018-01-09 07:34:52.001 [INFO ] [onplm.internal.device.MessageHandler] - DimmerRequestReplyHandler: set device 2B.ED.BE to level 0

2018-01-09 07:35:02.716 [INFO ] [onplm.internal.device.MessageHandler] - DimmerRequestReplyHandler: set device 2F.E1.76 to level 0

2018-01-09 07:35:04.063 [INFO ] [onplm.internal.device.MessageHandler] - LightOnDimmerHandler: device 27.2A.DC was turned on REGULAR. Sending poll request to get actual level

==> /var/log/openhab2/events.log <==

2018-01-09 07:35:04.064 [vent.ItemStateChangedEvent] - JoryLavaLamps changed from 0 to 100

==> /var/log/openhab2/openhab.log <==

2018-01-09 07:35:05.409 [INFO ] [onplm.internal.device.MessageHandler] - DimmerRequestReplyHandler: set device 27.2A.DC to level 61

==> /var/log/openhab2/events.log <==

2018-01-09 07:35:05.410 [vent.ItemStateChangedEvent] - JoryLavaLamps changed from 100 to 61

==> /var/log/openhab2/openhab.log <==

2018-01-09 07:35:10.229 [INFO ] [onplm.internal.device.MessageHandler] - LightOnDimmerHandler: device 27.2A.DC was turned on REGULAR. Sending poll request to get actual level

==> /var/log/openhab2/events.log <==

2018-01-09 07:35:10.230 [vent.ItemStateChangedEvent] - JoryLavaLamps changed from 61 to 100

==> /var/log/openhab2/openhab.log <==

2018-01-09 07:35:11.575 [INFO ] [onplm.internal.device.MessageHandler] - DimmerRequestReplyHandler: set device 27.2A.DC to level 100

2018-01-09 07:35:13.437 [INFO ] [onplm.internal.device.MessageHandler] - DimmerRequestReplyHandler: set device 2F.83.A2 to level 0

2018-01-09 07:35:17.559 [INFO ] [onplm.internal.device.MessageHandler] - LightOffDimmerHandler: device 27.2A.DC was turned off REGULAR.

==> /var/log/openhab2/events.log <==

2018-01-09 07:35:17.560 [vent.ItemStateChangedEvent] - JoryLavaLamps changed from 100 to 0

==> /var/log/openhab2/openhab.log <==

2018-01-09 07:35:21.556 [INFO ] [onplm.internal.device.MessageHandler] - LightOffDimmerHandler: device 27.2A.DC was turned off REGULAR.

2018-01-09 07:35:24.159 [INFO ] [onplm.internal.device.MessageHandler] - DimmerRequestReplyHandler: set device 2F.E9.DB to level 0

2018-01-09 07:35:24.386 [INFO ] [onplm.internal.device.MessageHandler] - LightOffDimmerHandler: device 27.2A.DC was turned off REGULAR.

I’m not getting any loginfo anymore, I was when it was firing, So I believe the rule isn’t triggering at all anymore.

I will change the if statement to an else if statement and see if that makes any difference. and post the logs again

Unfortunately I don’t have any solutions but will say that I chased these types of problems since migrating from 1.8 to OH 2 a year ago. Logging isn’t usually the fix for this issue because as you are seeing, logging also stops when the rule stops. It got so bad for me that I actually have 2 instances of OH running on two separate machines that monitor each other and rules have a clutch that switch which server is active because rule processing would go down often and randomly.

I’ve been on 2.2 since it came out and thus far, rules have been working without a hangup. You may want to consider trying 2.2 to see if your problem resolves.

I did switch from mysql to jdbc-mysql and a few other little tweaks during my 2.1 - 2.2 migration so there could be other things that helped.

I quite agree. The logInfo is there to determine the nature of what has gone wrong - is the rule not firing, is it that values are not as expected etc.

I guess “fix” wasn’t the right word.

My point is that I have tried repeatedly to raise logging level on the rules engine to debug and trace as well as filling all of my rules with debugging logs and in the end, the rules just simply stop processing and none of the logs really show anything. Others found the same thing. One moment a rule fires and all rule based logs spew, the next moment, the event shows the item change and absolutely nothing happens in the root logger.

Because we can’t put a finger on or show exactly where, when, why or a reproducible setup… we have gained little traction in looking for assistance.

At this point, I’m holding my breath that 2.2 and or tweaks I made during the migration have fixed it as my rules have been humming along without pause.

Have you tried putting the rules that dont fire in their own .rules file? Its what I’ve been doing and it seems to work out alright, I was just really wanted to organize my rules into fewer, more comprehensive files. I’ve got to say it is kind of a bummer others have been able to witness this issue, but have found no solutions.

I’ve updated to 2.2 now, still having the same issue, Im currently using mysql persistence, if I have time today I’ll se about moving to jdbc-mysql. What other tweaks have you made?

I have the same rough rules setup as you. I have:

default.rules - lights and generic stuff
climatecontrol.rules - heat and ac
security.rules - security system based rules

I haven’t tried breaking them out any further. If I had a single or collection of rules that stopped I would try something like that but my experience was that when a rule stopped, they ALL stopped.

There were a lot of little tweaks that probably have no consequence. I migrated to stretch from jessie. I changed exec, astro and network bindings to their 2.0 counterparts. I stopped using weather binding and starting using the wunderground binding instead. Database changed from mysql to mariadb.

Have you or anyone else with this problem filed an issue?

There have been a few that have opened one or two but they usually don’t go anywhere because we cannot reproduce or get any good logs as nothing consistent is happening and no errors are thrown… it just stopped triggering rules. I personally haven’t opened any issues because I knew I wouldn’t be able to substantiate my issue so why bother.

We did once track down a bug in harmony binding that helped some.

Just poking around in issues I see https://github.com/eclipse/smarthome/issues/4103

I do have a decent collection of sleeps (very short designed to delay a second for persistence to catch up) that perhaps that was my issue and why I no longer (thus far) see it in 2.2. IDK. Jury is still out. I sometimes would get hours, sometimes days and occasionally a few weeks before it would crash.