Rule to turn on device and set running time

hello, i’m becoming crazy to move these rules from OH2 to OH3.
i’m not a programmer, and especially in rules structure i find many difficulties, so i have to ask you.
i have these rules that from sitemap can set timer to activate and set running-time for my conditioners.
i have searched a lot on forum post to find sothing that can hekp but nothing found.
better is to set this rule from webUI instead from file, but main thing is that this rule works.
can anyone help?

actually the error is:

[ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID 'alarm-2' failed: cannot invoke method public abstract org.openhab.core.types.State org.openhab.core.items.Item.getState() on null in alarm

here is the rule code:

var Timer timerPERSON1Wecker = null

rule "Presets Mattina-Sera"

when
		Item PRESETS_MATTINA_SERA received command
then
	var int sollMinute
	var int sollStunde
	var int RunTime
	switch (PRESETS_MATTINA_SERA.state)
		{
		//MATTINA
		case 1:	{
			sollStunde=7
			sollMinute=0
		        RunTime=30
			}

		//SERA
		case 2:	{
			sollStunde=20
		        sollMinute=30
		        RunTime=30
			}
		}

	//set hour,minute,runtime items for each day
	var i = 7
	var Giorno= "NA"
        //don't change saturday/sunday. set i max=7 and uncomment cases if you have to work weekends, you unlucky soul
	while ((i=i+1) <= 5) 
	{
	switch i
		{
		case 1: Giorno = "LUNEDI"
		case 2: Giorno = "MARTEDI"
		case 3: Giorno = "MERCOLEDI"
		case 4: Giorno = "GIOVEDI"
		case 5: Giorno = "VENERDI"
		case 6: Giorno = "SABATO"
		case 7: Giorno = "DOMENICA"
		}

	//set all hours
	gPERSON1Wecker.members.filter(s|s.name == "PERSON1_"+Giorno+"_H").forEach[s | s.postUpdate(sollStunde)]

	//set all minutes
	gPERSON1Wecker.members.filter(s|s.name == "PERSON1_"+Giorno+"_M").forEach[s | s.postUpdate(sollMinute)]

	//set runtimes
	gPERSON1Wecker.members.filter(s|s.name == "PERSON1_"+Giorno+"_RUN").forEach[s | s.postUpdate(RunTime)]
	}
end


rule "Wecker PERSON1"
    when
        Time cron "0 0/1 * * * ?"
    then
    var Oggi = ""
    var boolean Wecken = false
    var int sollMinute
    var int sollStunde
    var int RunTime
    
    switch now.getDayOfWeek
	{
        case 1: Oggi = "LUNEDI"
        case 2: Oggi = "MARTEDI"
        case 3: Oggi = "MERCOLEDI"
        case 4: Oggi = "GIOVEDI"
        case 5: Oggi = "VENERDI"
        case 6: Oggi = "SABATO"
        case 7: Oggi = "DOMENICA"
	}

    if (gPERSON1Wecker.members.filter[s | s.name == "PERSON1_"+Oggi].head.state == ON) 
		{
		sollMinute = (gPERSON1Wecker.members.filter[s | s.name == "PERSON1_"+Oggi+"_M"].head.state as Number).intValue
		sollStunde = (gPERSON1Wecker.members.filter[s | s.name == "PERSON1_"+Oggi+"_H"].head.state as Number).intValue
		RunTime = (gPERSON1Wecker.members.filter[s | s.name == "PERSON1_"+Oggi+"_RUN"].head.state as Number).intValue
		Wecken = true
		}

		if (sollMinute == now.getMinuteOfHour && sollStunde == now.getHourOfDay && Wecken==true && PERSON1_WECKER_PRESETS.state==1)
                        {
                        //WECKER_AKTIV to ON, so you can react to a move sensor downstairs or in the kitchen
                        // i use this for a squeezeboxspeak "Good morning. it is soandsomuch degrees"
                        sendCommand(PERSON1_WECKER_AKTIV,ON)
                        sendCommand(DaikinSoggiorno_Power, ON)
                        //Do Stuff here, like turn on lights,coffee machine and/or radio

                        timerPERSON1Wecker = createTimer(now.plusMinutes(RunTime)) [|
                                //turn lights,radio etc. of after defined time for day.
                                //sanity check turn off wecker_aktiv
                                sendCommand(PERSON1_WECKER_AKTIV,OFF)
                                sendCommand(DaikinSoggiorno_Power, OFF)
                                timerPERSON1Wecker = null
                                ]
                        }


		else if (sollMinute == now.getMinuteOfHour && sollStunde == now.getHourOfDay && Wecken==true && PERSON1_WECKER_PRESETS.state==2)
			{
                        //WECKER_AKTIV to ON, so you can react to a move sensor downstairs or in the kitchen
                        // i use this for a squeezeboxspeak "Good morning. it is soandsomuch degrees"
			sendCommand(PERSON1_WECKER_AKTIV,ON)
			sendCommand(DaikinCamera_Power, ON)
			//Do Stuff here, like turn on lights,coffee machine and/or radio
			
			timerPERSON1Wecker = createTimer(now.plusMinutes(RunTime)) [|
				//turn lights,radio etc. of after defined time for day.
                                //sanity check turn off wecker_aktiv
				sendCommand(PERSON1_WECKER_AKTIV,OFF)
				sendCommand(DaikinCamera_Power, OFF)
				timerPERSON1Wecker = null
				]
			}

		else if (sollMinute == now.getMinuteOfHour && sollStunde == now.getHourOfDay && Wecken==true && PERSON1_WECKER_PRESETS.state==3)
                        {
                        //WECKER_AKTIV to ON, so you can react to a move sensor downstairs or in the kitchen
                        // i use this for a squeezeboxspeak "Good morning. it is soandsomuch degrees"
                        sendCommand(PERSON1_WECKER_AKTIV,ON)
                        sendCommand(DaikinCameretta_Power, ON)
                        //Do Stuff here, like turn on lights,coffee machine and/or radio

                        timerPERSON1Wecker = createTimer(now.plusMinutes(RunTime)) [|
                                //turn lights,radio etc. of after defined time for day.
                                //sanity check turn off wecker_aktiv
                                sendCommand(PERSON1_WECKER_AKTIV,OFF)
                                sendCommand(DaikinCameretta_Power, OFF)
                                timerPERSON1Wecker = null
                                ]
                        }


end

thanks!

The error comes from the second rule defined in alarm.rules.

The error is complaining about a call to getState().

So look at all the lines containing .getState, .state. Add some logging to see what all the parts of those lines exist. Add logging to see which of those lines it’s really failing on.

Let’s say it’s

sollMinute = (gPERSON1Wecker.members.filter[s | s.name == "PERSON1_"+Oggi+"_M"].head.state as Number).intValue

What’s Oggi?
What’s "Person1_"+Oggi+"_M" evaluate to? Do you in fact have an Item of that name and is that Item a member of gPERSON1Wecker?

If that Item exists, what’s it’s state? Is it a number or is it NULL or UNDEFINED?

Hi Rich I have the same set of rules which work nicely on OH2 but somehow fall over on OH3. It is the Morning Alarm code example posted a few years back here:
alarm clock

All the items exist and I have made sure none of them are Null values but it still gives the same error.

script execution of rule with UID 'alarm_masterbed-2' failed: cannot invoke method public abstract org.openhab.core.types.State org.openhab.core.items.Item.getState() on null in alarm_masterbed

Can you give an example of how we can debug these lines using logging? There is something about OH3 which has caused this to stop working.

It might be worth looking at the Alarm Clock rule template in the Marketplace. No code. Installs like an add-on. You don’t need a separate Item for hour, minute, second. Uses DateTime Items that can be populated from anywhere: Astro, iCal binding, MainUI Widgets, Android Alarm, etc. Seven Items with seven rules you don’t even have to write, just install and configure. Way less work than trying to make that old and complicated example work.

Not really because debugging a rule isn’t something you can just copy and paste. You have to understand what the rule does, how it does it, and from there you can focus in on where things are going wrong.

How do you know what line of code it’s failing on? Use the clues in the error message. If that doesn’t provide enough information, litter your rule with log statements. The last log statement you see before the error tells you that the error takes place between that log entry and the next log entry. If you have to put a log statement every other line of code.

What’s alarm_masterbed? If it’s an Item what’s its state in the rule? Log that out.

thanks the Marketplace rule looks like it may be useful but ideally I’d just like to get this working - Im still using regular sitemaps which work fine.
I’ve got alarms set up for 4 bedrooms so quite a lot of code already in place. I can see all the items in Visual Basic and they are populated fine.

This is the Masterbed_alarm rule file, there are 3 others but they all get the same error

var Timer timerMasterbedAlarm = null

rule "Masterbed preset load"
	when
		Item MASTERBED_ALARM_PRESETS received command
then
	var int shiftMinute
    var int shiftHour
    var int RunTime
	switch (MASTERBED_ALARM_PRESETS.state){
		//early shift
		case 1:{
			shiftHour=6
    		shiftMinute=35
    		RunTime=30
		}
		//late shift
		case 2:{
			shiftHour=9
    		shiftMinute=0
    		RunTime=30			
		}
	}
	//set hour,minute,runtime items for each day
	var i = 0
	var Day= "NA"
        //don't change saturday/sunday. set i max=7 and uncomment cases if you have to work weekends, you unlucky soul
	while ((i=i+1) <= 5) {
    	switch i{
        	case 1: Day = "MO"
        	case 2: Day = "TU"
        	case 3: Day = "WE"
        	case 4: Day = "TH"
        	case 5: Day = "FR"
        	//case 6: Day = "SA"
        	//case 7: Day= "SU"
    	}
    	//set all hours
    	gMasterbedAlarm.members.filter(s|s.name == "MASTERBED_ALARM_"+Day+"_H").forEach[s | s.postUpdate(shiftHour)]
    	//set all minutes
    	gMasterbedAlarm.members.filter(s|s.name == "MASTERBED_ALARM_"+Day+"_M").forEach[s | s.postUpdate(shiftMinute)]
    	//set runtimes
    	gMasterbedAlarm.members.filter(s|s.name == "MASTERBED_ALARM_"+Day+"_RUN").forEach[s | s.postUpdate(RunTime)]
	}
end


rule "Alarm MASTERBED"
    when
        Time cron "0 0/1 * * * ?" //every minute of the hour
    then
    var Today = ""
    var boolean Alarm = false
    var int shiftMinute
    var int shiftHour
    var int RunTime
    
    switch now.getDayOfWeek{   //function to check what day of week it is 1 = Monday
        case 1: Today= "MO"
        case 2: Today= "TU"
        case 3: Today= "WE"
        case 4: Today= "TH"
        case 5: Today= "FR"
        case 6: Today= "SA"
        case 7: Today= "SU"
    }
    if (gMasterbedAlarm.members.filter[s | s.name == "MASTERBED_ALARM_"+Today].head.state == ON) {
		shiftMinute = (gMasterbedAlarm.members.filter[s | s.name == "MASTERBED_ALARM_"+Today+"_M"].head.state as Number).intValue
		shiftHour = (gMasterbedAlarm.members.filter[s | s.name == "MASTERBED_ALARM_"+Today+"_H"].head.state as Number).intValue
		RunTime = (gMasterbedAlarm.members.filter[s | s.name == "MASTERBED_ALARM_"+Today+"_RUN"].head.state as Number).intValue
		Alarm = true
	}
 
		if (shiftMinute == now.getMinuteOfHour && shiftHour == now.getHourOfDay && Alarm==true) {
                        //ALARM_AKTIV to ON, so you can react to a move sensor downstairs or in the kitchen
                        // i use this for a squeezeboxspeak "Good morning. it is soandsomuch degrees"
                        // see rule "react to move"
                        //remove all references if you don't want/need this
			sendCommand(MASTERBED_ALARM_AKTIV,ON)	
			//Do Stuff here, like turn on lights,coffee machine and/or radio
			Masterbed_open_blinds.sendCommand(ON)
    		Lt_Masterbed_Bath_Ceiling.sendCommand(ON) 
			MasterbedwcShutter.sendCommand(UP)
			if (Sonos_State.state != "PLAYING")  //if not already playing 
	    	{
	    	All_Zones.sendCommand(OFF)  //just in case zones on
			Sonos_Volume.sendCommand(20)
			Sonos_Shuffle.sendCommand(ON)
	    	Sonos_Favorite.sendCommand("Alarm")
			}
			masterbed_music.sendCommand(ON)
	    	timerMasterbedAlarm = createTimer(now.plusMinutes(RunTime)) [|
			//turn lights,radio etc. off after defined time for day.
            //sanity check turn off wecker_aktiv
			masterbed_music.sendCommand(OFF)
			Lt_Masterbed_Bath_Ceiling.sendCommand(OFF) 
			//Lt_Masterbed_Mezz.sendCommand(OFF) 
            sendCommand(MASTERBED_ALARM_AKTIV,OFF)
			timerMasterbedAlarm = null
			]
		}
end

Well, I provided you with all the steps necessary to narrow the problem down to a specific line of code and then to figure out what is going on on that line of code.

You will not be able to solve this without examining these rules one by one, determining which line of code is failing, and gather more information about why that line could be failing. No one else can do that for you.

can you tell us how to debug this? this rule helped me some years ago and now fixing this, can help maybe other users…

thanks

debugging a rule isn’t something you can just copy and paste. You have to understand what the rule does, how it does it, and from there you can focus in on where things are going wrong.

How do you know what line of code it’s failing on? Use the clues in the error message. If that doesn’t provide enough information, litter your rule with log statements. The last log statement you see before the error tells you that the error takes place between that log entry and the next log entry. If you have to put a log statement every other line of code.

Ok after a few hours of searching it appears the issue is to do with the way OH3 handles date and time.

So instead of
now.getDayOfWeek
you use
now.getDayOfWeek.getValue.intValue

and for
now.getMinuteOfHour
now.getHourOfDay

use

ZonedDateTime.now.getMinute
ZonedDateTime.now.getHour

I did add some logging which helped to some extent - so I learnt that to output Var you do the following:

logInfo("alarm.rule", "Today=" + Today)

This was coming up null so that lead me to search for problems with the getdayofweek issue.

Anyway these seem to be working now which is the main thing - I was not looking forward to changing 5 Alarms and all the code that goes with them. I’ll put a note on the original post for the code in case others have the same problem.

yes that’s it! i was near to solution, because i found too that now has been changed in fact i have used that in another script but not this one: now.getDayOfWeek.getValue.intValue

thanks a lot!