[SOLVED] Need help in setting up a Window/Heater rule

Hi all,

I would like to set up a rule that sets my homematic IP heater controller to 5 degree when I open the window.

What I have so far:

var Float HeizungSetting = 5.00

rule "heizungKz"
when
    Item FensterKzL changed
then
{
	if (FensterKzL == OPEN)
	{
	HeizungSetting = HzTargetTempKz.state
	HzTargetTempKz.sendCommand(5.00)
	}
	else
	{
	 HzTargetTempKz = HeizungSetting
	}
}	
end

I would like to store the actual heater setting in a variable called “HeizungSetting” when the window gets opened and then ste the temp down to 5 degree C. When the windows gets closed set the temp back to what it was set before the windows got opened.

When I run the rule like shown above a I get a Rule 'heizungKz': An error occurred during the script execution: Cannot assign a value in null context. error.

I just tried to create the rule but there must be some syntax error or whatever, I guess this is an easy task for th epros here…

Thanks in advance!

Change

To

HeizungSetting = HzTargetTempKz.state as Number

Ok, I fixed my initial code to what you have suggested:

var Float HeizungSetting = 5.00

rule "heizungKz"
when
    Item FensterKzL changed
then
{
	if (FensterKzL == OPEN)
	{
	HeizungSetting = HzTargetTempKz.state as Number
	HzTargetTempKz.sendCommand(5.00)
	}
	else
	{
	 HzTargetTempKz = HeizungSetting
	}
}	
end

Unfortunately it still doesn´t work and the error message still appears.

In the first part, HzTargetTemp is an Item that you send a command too. I think that’ll be true in the second part of the rule as well?

You also have an extra { before the if statement

// var Float HeizungSetting = 5.00

rule "heizungKz"
when
    Item FensterKzL changed
then

        var HeizungSetting = storeStates(HzTargetTempKz)

	if (FensterKzL.state == OPEN) {
	
	     HzTargetTempKz.sendCommand(5.00)
	}
	    else (FensterKzL.state == CLOSED) {
                 restoreStates(HeizungSetting)
//	         HzTargetTempKz = HeizungSetting
	}
end

You may need to use
var HeizungSetting = storeState(HzTargetTempKz.state as Number)
Just try it and change if needed.

mmh, when I try your approach I get

 Rule 'heizungKz': The name 'storeState' cannot be resolved to an item or type; line 6, column 30, length 26

what I also tried is this:

var Float HeizungSetting = 5.00

rule "heizungKzSetting"
when
    Item HzTargetTempKz changed
then
	HeizungSetting = HzTargetTempKz.state as Number
end


rule "heizungKz"
when
    Item FensterKzL changed
then

	if (FensterKzL == OPEN)
	{
	HzTargetTempKz.sendCommand(5.00)
	}
	else
	{
	 HzTargetTempKz.sendCommand(HeizungSetting)
	}

end

Here I ´m trying to get the actual temp setting right when setting are being changed. So I thought I could just use the variable HeizungSetting from my rule “heizungKz” but it does not work for some reason, too. This is my output in the log file:

2018-10-18 19:17:34.302 [INFO ] [el.core.internal.ModelRepositoryImpl] - Refreshing model 'heizung.rules'

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

2018-10-18 19:17:48.319 [vent.ItemStateChangedEvent] - FensterKzL changed from OPEN to CLOSED

2018-10-18 19:17:48.709 [ome.event.ItemCommandEvent] - Item 'HzTargetTempKz' received command 5.0

2018-10-18 19:17:48.748 [vent.ItemStateChangedEvent] - HzTargetTempKz changed from 15.50 to 5.0

2018-10-18 19:18:04.774 [vent.ItemStateChangedEvent] - HzTargetTempKz changed from 5.00 to 7.50

2018-10-18 19:18:09.745 [vent.ItemStateChangedEvent] - FensterKzL changed from CLOSED to OPEN

2018-10-18 19:18:09.781 [ome.event.ItemCommandEvent] - Item 'HzTargetTempKz' received command 7.50

So I closed my window and it then gets send to 5.0°C, probably because that´s how the var HeizungSetting is being initialized with 5.0. Looks good. But then it does not work anymore. I manually changed from 5 to 7.5 what is also recognized by openhab as you can see but when opening the window it does not set to 5.0 but is sending 7.5 again.

Looks like the first rule will change the var when the HzTargetTempKz is changed and the second rule uses that new value.

storeState per the doc’s should be storeStates I missed putting the s on.:roll_eyes: same goes for restoreState it needs the s as well restoreStates

This should store the current setting when the window is opened. The sendCommand will set the temp to 5. When the window is shut, restoreStates should return the setting to whatever it was before the window is opened.

well I found another problem which makes everything else unimportant in the moment.

It seems like this part

if (FensterKzL == OPEN)

is not correctly recognized because openhab always jumps in to the “else” part and sets the temp to 8 °C (I fixed that value to 8° for testing purpose).
So it does not recognize if the window is open or closed. For example if I write

else if (FensterKzL == CLOSED)

this will be skipped as well.

Any idea what could be the reason for this behavior? I know from the log that the communication between my windows sensor and openhab is working and I get the state report as CLOSED or OPEN. I also tried 0 and 1 but that didn´t work either.

Change the else to another if or try testing with a return;

else
	{
	 return;  // do nothing
	}

See here for more about if, else, and else if https://www.w3schools.com/js/js_if_else.asp

Also where did you set the temp to 8, that might make a difference.

This is an Item, it’s the tem.state you are interested in.
It’s a hard lesson in rules that Items must not be treated like ordinary variables. A mistake I’m sure we all carry on making, bu you more quickly learn how to spot it :slight_smile:

2 Likes

Your not storing the previous temp so just make the rule run when the window is open.

rule "heizungKz"
when
    Item FensterKzL changed from CLOSED to OPEN
then
	HzTargetTempKz.sendCommand(5.00)
end

@rossko57 Grrrrr I should have noticed that.:expressionless: Nice hint by the way.:smiley:

Yes, that was the issue, thanks for that!

So for now the following code is working so far that the heater will be set to 5 degree C when the window opens and will be set to the HeizungSetting initialization value when it gets closed. I am still not able to get the actual set temperature to save in a var (HeizungSetting) to restore the last temp setting when the window gets closed.

var Float HeizungSetting = 5.00

rule "heizungKzSetting"
when
    Item HzTargetTempKz changed
then
	HeizungSetting = HzTargetTempKz.state as Number
end

rule "heizungKz"
when
    Item FensterKzL changed
then

	if (FensterKzL.state == OPEN)
	{
	HzTargetTempKz.sendCommand(5.00)
	}
	else if (FensterKzL.state == CLOSED)
	{
	 HzTargetTempKz.sendCommand(HeizungSetting)
	}

end

edit:

did some troubleshooting on this part:

var Float HeizungSetting = 5.00

rule "heizungKzSetting"
when
    Item HzTargetTempKz changed
then
	HeizungSetting = HzTargetTempKz.state as Number
	logInfo("heizung.rules", HeizungSetting)
end

What I get in the logfile after setting temp manually is this:

2018-10-19 10:11:16.803 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'heizungKzSetting': An error occurred during the script execution: Could not invoke method: org.eclipse.smarthome.model.script.actions.LogAction.logInfo(java.lang.String,java.lang.String,java.lang.Object[]) on instance: null
logInfo("heizung.rules", HeizungSetting.toString)

But you might want to block that if the window is open…

var Float HeizungSetting = 5.00

rule "heizungKzSetting"
when
    Item HzTargetTempKz changed
then
    if (FensterKzL.state == CLOSED) {
        HeizungSetting = HzTargetTempKz.state as Number
        logInfo("heizung.rules", HeizungSetting)
    } else if (HeizungSetting != 5) {
        logInfo("heizung.rules", "Window is opened - Resetting temp to 5")
        HeizungSetting = 5
        HzTargetTempKz.sendCommand(HeizungSetting)
    }
end
2018-10-19 10:28:37.282 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'heizungKzSetting': An error occurred during the script execution: Could not invoke method: java.lang.Float.toString() on instance: 10.00

I can see the value at the end what helps me a bit, but the rule stops executing after this error…

var Number HeizungSetting = 5.00
1 Like

Yes, finally its working! Don´t understand why I have to use Number instead of float (because I think this should be a float o0) but now my whole code is working the way I want it to! Thank you all guys, below you can find my working code:

var Number HeizungSetting = 5.00

rule "heizungKzSetting"
when
    Item HzTargetTempKz changed
then
	if (HzTargetTempKz.state >5.0)
	{
	HeizungSetting = HzTargetTempKz.state as Number
	}
	else{
	break
	}
end

rule "heizungKz"
when
    Item FensterKzL changed
then

	if (FensterKzL.state == OPEN)
	{
	HzTargetTempKz.sendCommand(5.00)
	}
	else if (FensterKzL.state == CLOSED)
	{
	HzTargetTempKz.sendCommand(HeizungSetting)
	}

end

A float is a java primitive type. It is discouraged to use primitive types in the rules DSL for several reasons.

  • The methods sendCommand and postUpdates accept Number types. They will convert a float or int to a Number before sending it to the binding
  • The primitive types don’t have methods like .toString
  • The compilation time gets significantly longer when using primitives

Numbers are easier, you don’t have to worry about type, methods… You can do math with them, you can use them with comparison opertors… Use Numbers. Numbers are the way to go.

UNLESS you use datetime types in which case you need to use int types for methods like:

   now.plusMinutes(myMinutes)

myMinutes MUST be an int type

You can convert a Number to an int type in several ways, I use:
var int myInt = Integer::parseInt(myNumber.toString)

I am sure there is a better way but that works for me.

Great, thanks for your explanation, that will help on my coming projects!