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…
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.
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. 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.
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
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
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…
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.