Code cleanup - nested ifs and whens

Background: our country’s (South Africa) electrical supply is dodgy, and the provider is implementing loadshedding, effectively shutting down parts of the country’s electrical supply to manage the grid load. It is divided into Phases, with each Phase progressively meaning that you’ll have blackouts more often. We have schedules for these blackouts.

My Narada battery isn’t too good at supporting the Victron inverter to switch over when the grid loses power. To alleviate this, I switch to inverter only mode a few minutes before the blackout.

My switching commands and basic cron jobs are working. I currently do the switch irrespective of whether we have loadshedding or not.

Now to my question: I want to implement a five state switch to only switch over when we do have loadshedding, and only if we have loadshedding at the relevant Phase. But my code is looking terrible. I haven’t verified if the nested ifs work yet, but I’d like to hear if someone can offer suggestions as to better programming practise.

Goal of the code: check if it is 14:55 on the first of the month. (I have a Phase 1 slot at 15:00 on the first, and want to switch 5 minutes before then). Check if there is loadshedding in any of Phases 1-4 (“loadshedding” is a user controlled, 4-state, switch). If both conditions is true, do the switching.

The next portion will be to check for times where I have Phase 2 slots, and check if the “loadshedding” switch is set to Phases 2-4, and switch if necessary.

//rules to switch to "inverter only" before loadshedding starts

rule "loadshedding_before"

//stage 1
when Time cron "0 55 14 1 * ? *"
	or Time cron "0 55 22 2 * ? *"
	or Time cron "0 55 6 4 * ? *"
	or Time cron "0 55 12 5 * ? *"
	or Time cron "0 55 20 6 * ? *"
	or Time cron "0 55 4 8 * ? *"
	or Time cron "0 55 10 9 * ? *"
	or Time cron "0 55 18 10 * ? *"
	or Time cron "0 55 2 12 * ? *"
	or Time cron "0 55 8 13 * ? *"
	or Time cron "0 55 16 14 * ? *"
	or Time cron "0 55 0 16 * ? *"
	or Time cron "0 55 6 17 * ? *"
	or Time cron "0 55 14 18 * ? *"
	or Time cron "0 55 22 19 * ? *"
	or Time cron "0 55 4 21 * ? *"
	or Time cron "0 55 12 22 * ? *"
	or Time cron "0 55 20 23 * ? *"
	or Time cron "0 55 2 25 * ? *"
	or Time cron "0 55 10 26 * ? *"
	or Time cron "0 55 18 27 * ? *"
	or Time cron "0 55 0 29 * ? *"
	or Time cron "0 55 8 30 * ? *"
	or Time cron "0 55 16 31 * ? *"
then
	if (loadshedding.state.toString == "1" || loadshedding.state.toString == "2" || loadshedding.state.toString == "3" || loadshedding.state.toString == "4")
	{
			//logInfo("loadshedding.rules","enter")
			sendBroadcastNotification("Loadshedding Phase 1")
			//val mqttActions = getActions("mqtt","mqtt:broker:756389ee")
			//mqttActions.publishMQTT("W/7c3866560fa4/vebus/261/Mode",'{"value": 2}')
			//logInfo("loadshedding.rules","exit")		
	}
	else when
		//stage 2
		or Time cron "0 55 6 1 * ? *"
		or Time cron "0 55 14 2 * ? *"
		or Time cron "0 55 22 3 * ? *"
		or Time cron "0 55 4 5 * ? *"
		or Time cron "0 55 12 6 * ? *"
		or Time cron "0 55 20 7 * ? *"
		or Time cron "0 55 2 9 * ? *"
		or Time cron "0 55 10 10 * ? *"
		or Time cron "0 55 18 11 * ? *"
		or Time cron "0 55 0 13 * ? *"
		or Time cron "0 55 8 14 * ? *"
		or Time cron "0 55 16 15 * ? *"
		or Time cron "0 55 6 18 * ? *"
		or Time cron "0 55 14 19 * ? *"
		or Time cron "0 55 22 20 * ? *"
		or Time cron "0 55 4 22 * ? *"
		or Time cron "0 55 12 23 * ? *"
		or Time cron "0 55 20 24 * ? *"
		or Time cron "0 55 2 26 * ? *"
		or Time cron "0 55 10 27 * ? *"
		or Time cron "0 55 18 28 * ? *"
		or Time cron "0 55 0 30 * ? *"
		or Time cron "0 55 8 31 * ? *"
		then
			if (loadshedding.state.toString == "2" || loadshedding.state.toString == "3" || loadshedding.state.toString == "4")
			{
				//logInfo("loadshedding.rules","enter")
				sendBroadcastNotification("Loadshedding Phase 2")
				//val mqttActions = getActions("mqtt","mqtt:broker:756389ee")
				//mqttActions.publishMQTT("W/7c3866560fa4/vebus/261/Mode",'{"value": 2}')
				//logInfo("loadshedding.rules","exit")		
			}
		end
		else when
			//stage 3
			Time cron "0 55 6 2 * ? *"
			or Time cron "0 55 4 6 * ? *"
			or Time cron "0 55 12 7 * ? *"
			or Time cron "0 55 2 10 * ? *"
			or Time cron "0 55 10 11 * ? *"
			or Time cron "0 55 0 14 * ? *"
			or Time cron "0 55 8 15 * ? *"
			or Time cron "0 55 6 19 * ? *"
			or Time cron "0 55 4 23 * ? *"
			or Time cron "0 55 12 24 * ? *"
			or Time cron "0 55 2 27 * ? *"
			or Time cron "0 55 10 28 * ? *"
			then
				if (loadshedding.state.toString == "3" || loadshedding.state.toString == "4")
				{
					//logInfo("loadshedding.rules","enter")
					sendBroadcastNotification("Loadshedding Phase 3")
					//val mqttActions = getActions("mqtt","mqtt:broker:756389ee")
					//mqttActions.publishMQTT("W/7c3866560fa4/vebus/261/Mode",'{"value": 2}')
					//logInfo("loadshedding.rules","exit")		
				}
			end 
			else when
				//stage 4
				Time cron "0 55 22 1 * ? *"
				or Time cron "0 55 6 3 * ? *"
				or Time cron "0 55 4 7 * ? *"
				or Time cron "0 55 12 8 * ? *"
				or Time cron "0 55 2 11 * ? *"
				or Time cron "0 55 10 12 * ? *"
				or Time cron "0 55 16 13 * ? *"
				or Time cron "0 55 0 15 * ? *"
				or Time cron "0 55 8 16 * ? *"
				or Time cron "0 55 6 20 * ? *"
				or Time cron "0 55 12 21 * ? *"
				or Time cron "0 55 4 24 * ? *"
				or Time cron "0 55 10 25 * ? *"
				or Time cron "0 55 2 28 * ? *"
				or Time cron "0 55 8 29 * ? *"
				or Time cron "0 55 1 31 * ? *"
				then
					if (loadshedding.state.toString == "4")
					{
						//logInfo("loadshedding.rules","enter")
						sendBroadcastNotification("Loadshedding Phase 4")
						//val mqttActions = getActions("mqtt","mqtt:broker:756389ee")
						//mqttActions.publishMQTT("W/7c3866560fa4/vebus/261/Mode",'{"value": 2}')
						//logInfo("loadshedding.rules","exit")
					}
				end
			end
		end
	end
end

Mmm, realized that I wrote myself into corners; my poor code has zero chance of working. So please don’t worry about the functioning of the code, but if there are any suggestions as to better coding principles, I’d appreciate it!

So my current version I’ve split it into 4 separate rules. It looks much tidier and makes more logical sense to me. Any suggestions as to better ways of doing it will still be appreciated.

//rules to switch to "inverter only" before loadshedding starts

rule "loadshedding_stage_1"
when Time cron "0 55 14 1 * ? *"
	or Time cron "0 55 22 2 * ? *"
	or Time cron "0 55 6 4 * ? *"
	or Time cron "0 55 12 5 * ? *"
	or Time cron "0 55 20 6 * ? *"
	or Time cron "0 55 4 8 * ? *"
	or Time cron "0 55 10 9 * ? *"
	or Time cron "0 55 18 10 * ? *"
	or Time cron "0 55 2 12 * ? *"
	or Time cron "0 55 8 13 * ? *"
	or Time cron "0 55 16 14 * ? *"
	or Time cron "0 55 0 16 * ? *"
	or Time cron "0 55 6 17 * ? *"
	or Time cron "0 55 14 18 * ? *"
	or Time cron "0 55 22 19 * ? *"
	or Time cron "0 55 4 21 * ? *"
	or Time cron "0 55 12 22 * ? *"
	or Time cron "0 55 20 23 * ? *"
	or Time cron "0 55 2 25 * ? *"
	or Time cron "0 55 10 26 * ? *"
	or Time cron "0 55 18 27 * ? *"
	or Time cron "0 55 0 29 * ? *"
	or Time cron "0 55 8 30 * ? *"
	or Time cron "0 55 16 31 * ? *"
then
	if (loadshedding.state.toString == "1" || loadshedding.state.toString == "2" || loadshedding.state.toString == "3" || loadshedding.state.toString == "4")
	{
			//logInfo("loadshedding.rules","enter")
			sendBroadcastNotification("Loadshedding Phase 1")
			//val mqttActions = getActions("mqtt","mqtt:broker:756389ee")
			//mqttActions.publishMQTT("W/7c3866560fa4/vebus/261/Mode",'{"value": 2}')
			//logInfo("loadshedding.rules","exit")		
	}
end

rule "loadshedding_stage_2"
when Time cron "0 55 6 1 * ? *"
	or Time cron "0 55 14 2 * ? *"
	or Time cron "0 55 22 3 * ? *"
	or Time cron "0 55 4 5 * ? *"
	or Time cron "0 55 12 6 * ? *"
	or Time cron "0 55 20 7 * ? *"
	or Time cron "0 55 2 9 * ? *"
	or Time cron "0 55 10 10 * ? *"
	or Time cron "0 55 18 11 * ? *"
	or Time cron "0 55 0 13 * ? *"
	or Time cron "0 55 8 14 * ? *"
	or Time cron "0 55 16 15 * ? *"
	or Time cron "0 55 6 18 * ? *"
	or Time cron "0 55 14 19 * ? *"
	or Time cron "0 55 22 20 * ? *"
	or Time cron "0 55 4 22 * ? *"
	or Time cron "0 55 12 23 * ? *"
	or Time cron "0 55 20 24 * ? *"
	or Time cron "0 55 2 26 * ? *"
	or Time cron "0 55 10 27 * ? *"
	or Time cron "0 55 18 28 * ? *"
	or Time cron "0 55 0 30 * ? *"
	or Time cron "0 55 8 31 * ? *"
then
	if (loadshedding.state.toString == "2" || loadshedding.state.toString == "3" || loadshedding.state.toString == "4")
	{
		//logInfo("loadshedding.rules","enter")
		sendBroadcastNotification("Loadshedding Phase 2")
		//val mqttActions = getActions("mqtt","mqtt:broker:756389ee")
		//mqttActions.publishMQTT("W/7c3866560fa4/vebus/261/Mode",'{"value": 2}')
		//logInfo("loadshedding.rules","exit")		
	}
end
		
rule "loadshedding_stage_3"		
when Time cron "0 55 6 2 * ? *"
	or Time cron "0 55 4 6 * ? *"
	or Time cron "0 55 12 7 * ? *"
	or Time cron "0 55 2 10 * ? *"
	or Time cron "0 55 10 11 * ? *"
	or Time cron "0 55 0 14 * ? *"
	or Time cron "0 55 8 15 * ? *"
	or Time cron "0 55 6 19 * ? *"
	or Time cron "0 55 4 23 * ? *"
	or Time cron "0 55 12 24 * ? *"
	or Time cron "0 55 2 27 * ? *"
	or Time cron "0 55 10 28 * ? *"
then
	if (loadshedding.state.toString == "3" || loadshedding.state.toString == "4")
	{
		//logInfo("loadshedding.rules","enter")
		sendBroadcastNotification("Loadshedding Phase 3")
		//val mqttActions = getActions("mqtt","mqtt:broker:756389ee")
		//mqttActions.publishMQTT("W/7c3866560fa4/vebus/261/Mode",'{"value": 2}')
		//logInfo("loadshedding.rules","exit")		
	}
end 

rule "loadshedding_stage_4" 
when Time cron "0 55 22 1 * ? *"
	or Time cron "0 55 6 3 * ? *"
	or Time cron "0 55 4 7 * ? *"
	or Time cron "0 55 12 8 * ? *"
	or Time cron "0 55 2 11 * ? *"
	or Time cron "0 55 10 12 * ? *"
	or Time cron "0 55 16 13 * ? *"
	or Time cron "0 55 0 15 * ? *"
	or Time cron "0 55 8 16 * ? *"
	or Time cron "0 55 6 20 * ? *"
	or Time cron "0 55 12 21 * ? *"
	or Time cron "0 55 4 24 * ? *"
	or Time cron "0 55 10 25 * ? *"
	or Time cron "0 55 2 28 * ? *"
	or Time cron "0 55 8 29 * ? *"
	or Time cron "0 55 1 31 * ? *"
then
	if (loadshedding.state.toString == "4")
	{
		//logInfo("loadshedding.rules","enter")
		sendBroadcastNotification("Loadshedding Phase 4")
		//val mqttActions = getActions("mqtt","mqtt:broker:756389ee")
		//mqttActions.publishMQTT("W/7c3866560fa4/vebus/261/Mode",'{"value": 2}')
		//logInfo("loadshedding.rules","exit")
	}
end

Hi,

How are you bringing load shedding status into OH? I’m looking at all the API’s written for Eskum’s site, but the site has changed etc. I’m assuming you’ve put your schedule in manually.

Just one thing on your rules, I have done some rules that run on item status change. So if the load shedding status changes, then run the rule.