[Solved] How to store a current setpoint value for later use in scripts

Hiya, I am currently creating some text-based rules in our OpenHAB3-setup to reduce our gas consumption.
The idea is that if a window is open longer than a set amount of time (in this case 2 minutes), the radiator(s) in that room should be set to 4 degrees celcius (which is the lowest setting allowed by our thermostats).
Once the window has been closed it should return to the previous value.

The problem is that I cannot get the previous temperature value stored.

When troubleshooting researching my issue, I found out that variables cannot be used outside the if (…) statement. All my tries to store the variable (time_Buero) into a String item and retrieve it for use have failed miserable however. I created a new “String” item and stored value of the time_Buero variable into it by using postUpdate. This worked, however all my tried of extracting the data from the STring item back into the variable failed.

Maybe someone has a similar script that works?

Here is my script (without the storing of data into the variable):


var String time_Buero
var Timer timer_fenster_Buero = null
rule "Heizungssteuerung Buero"

when
        Item Fenster_OG_AZ changed
then
        logInfo("Heizung", "Fenster Büro wurde bewegt")
        if ((Fenster_OG_AZ.state == OPEN)
          && (Heizung_Buero_Setpoint.state != 4|°C))
                {
                logInfo("Heizung", "Buero Heizung ist an und Fenster wurde geöffnet")
                val time_Buero = (ZonedDateTime.now())
                logInfo("Heizung", "Heizung Büro wird in 2 Minuten gedrosselt")
                logInfo("Heizung", "Wert ist aktuell (" + (time_Buero) +"): "+ (Heizung_Buero_Setpoint.historicState(time_Buero,"influxdb").state.toString))
                timer_fenster_Buero = createTimer(now.plusMinutes(2)) [ Heizung_Buero_Setpoint.sendCommand(4) ]
                }
        else
                if (Fenster_OG_AZ.state == OPEN)
                {
                logInfo("Heizung", "Buero Heizung ist aus und Fenster wurde geöffnet")
                }
        else
                if (Fenster_OG_AZ.state == CLOSED)
                {
                logInfo("Heizung", "Debug: " + (time_Buero))
                logInfo("Heizung", "Buero Heizung ist aus und Fenster wurde geschlossen")
                if(timer_fenster_Buero !== null)
                        {
                        timer_fenster_Buero.cancel()
                        timer_fenster_Buero = null
                        }
                logInfo("Heizung", "Heizung Büro wird auf den vorherigen Wert ("+ (Heizung_Buero_Setpoint.historicState(time_Buero).state.toString) +") von " + (time_Buero) + " gesetzt.")
                Heizung_Buero_Setpoint.sendCommand(Heizung_Buero_Setpoint.historicState(time_Buero,"influxdb").state)
                }
end

Here is the log output when the rule starts (Temperature has been set to a value >4 degrees celcius and the window has been opened):

2022-09-30 16:42:44.950 [INFO ] [rg.openhab.core.model.script.Heizung] - Fenster Büro wurde bewegt
2022-09-30 16:42:44.954 [INFO ] [rg.openhab.core.model.script.Heizung] - Buero Heizung ist an und Fenster wurde geöffnet
2022-09-30 16:42:44.954 [INFO ] [rg.openhab.core.model.script.Heizung] - Heizung Büro wird in 2 Minuten gedrosselt
2022-09-30 16:42:44.964 [INFO ] [rg.openhab.core.model.script.Heizung] - Wert ist aktuell (2022-09-30T16:42:44.954656+02:00[Europe/Berlin]): 10.0

Here is the log if the window is closed before the timer (2 minutes) is expired:

2022-09-30 16:42:47.128 [INFO ] [rg.openhab.core.model.script.Heizung] - Fenster Büro wurde bewegt
2022-09-30 16:42:47.129 [INFO ] [rg.openhab.core.model.script.Heizung] - Debug: null
2022-09-30 16:42:47.129 [INFO ] [rg.openhab.core.model.script.Heizung] - Buero Heizung ist aus und Fenster wurde geschlossen
2022-09-30 16:42:47.133 [INFO ] [rg.openhab.core.model.script.Heizung] - Heizung Büro wird auf den vorherigen Wert (10 °C) von null gesetzt.

Here is the log when the radiator thermostat has been set to 4 degrees celcius by the rule and the window has been closed:

2022-09-30 16:43:30.246 [INFO ] [rg.openhab.core.model.script.Heizung] - Fenster Büro wurde bewegt
2022-09-30 16:43:30.246 [INFO ] [rg.openhab.core.model.script.Heizung] - Buero Heizung ist an und Fenster wurde geöffnet
2022-09-30 16:43:30.246 [INFO ] [rg.openhab.core.model.script.Heizung] - Heizung Büro wird in 2 Minuten gedrosselt
2022-09-30 16:43:30.250 [INFO ] [rg.openhab.core.model.script.Heizung] - Wert ist aktuell (2022-09-30T16:43:30.246404+02:00[Europe/Berlin]): 10.0

2022-09-30 16:45:30.252 [INFO ] [openhab.event.ItemCommandEvent      ] - Item 'Heizung_Buero_Setpoint' received command 4
2022-09-30 16:45:30.256 [INFO ] [penhab.event.ItemStatePredictedEvent] - Item 'Heizung_Buero_Setpoint' predicted to become 4
2022-09-30 16:45:30.263 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Heizung_Buero_Setpoint' changed from 10 °C to 4 °C

2022-09-30 16:45:58.144 [INFO ] [rg.openhab.core.model.script.Heizung] - Fenster Büro wurde bewegt
2022-09-30 16:45:58.144 [INFO ] [rg.openhab.core.model.script.Heizung] - Debug: null
2022-09-30 16:45:58.144 [INFO ] [rg.openhab.core.model.script.Heizung] - Buero Heizung ist aus und Fenster wurde geschlossen
2022-09-30 16:45:58.147 [INFO ] [rg.openhab.core.model.script.Heizung] - Heizung Büro wird auf den vorherigen Wert (4 °C) von null gesetzt.
2022-09-30 16:45:58.160 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID 'heizungbuero-1' failed: An error occurred during the script execution: Could not invoke method: org.openhab.core.model.script.actions.BusEvent.sendCommand(org.openhab.core.items.Item,java.lang.String) on instance: null in heizungbuero

I don’t know how DSL rules deal with scope of variables but I have the impression that you use two kind of time_Buero variables.
One is defined globally ( as long as it is a text file rule )

var String time_Buero

The other one is defined as

val time_Buero

in local scope.

Does it work if you remove the val in front of the second definition ?

2 Likes

In this case, the time_Buero defined inside the rule gets priority over the ‘global’ version defined at the head of the file.
More precisely, the the time_Buero inside the rule is in turn inside the curly braces { } block of an if(). It lives inside that block, and evaporates at the closing }

So at different places in the rule. you’ll be updating or reading from different variables with the same name.
It’ll lead to insanity :slight_smile: so don’t do it … define a ‘global’ only once, at the file head. You can update or read that inside a rule without re-defining it.

2 Likes

Thanks for your help.
While investigating further I found a similar script that helped me in finding the correct way of storing the previous temperature in an item state, so I adjusted my rule and it seems to work fine now.

Here is my current rule in case it might help someone out:

// Temperatur auf die runtergeregelt wird
val Number tempOff_buero = 4
// Dauer in Minuten bis die Heizung runtergedreht wird
val Number timeOff_buero = 2
// Timervariable
var Timer timer_buero = null

rule "Heizungssteuerung Buero"
        when
        Item Fenster_OG_AZ changed
        then
                if((Fenster_OG_AZ.state == OPEN)
                && (Heizung_Buero_Setpoint.state != 4|°C))
                        {
                        logInfo("Heizung", "Buero Heizung ist an und das Fenster wurde geöffnet")
                        Heizung_Buero_Zeitstempel.postUpdate(new DateTimeType(now.minusSeconds(1)))
                        logInfo("Heizung", "Heizung Büro wird in " + (timeOff_buero) +" Minuten gedrosselt")
                        logInfo("Heizung", "Wert ist aktuell "+ (Heizung_Buero_Setpoint.historicState((Heizung_Buero_Zeitstempel.state as DateTimeType).getZonedDateTime()).state.toString))
                        timer_buero = createTimer(now.plusMinutes(timeOff_buero)) [Heizung_Buero_Setpoint.sendCommand(tempOff_buero)]
                        }
        else
                if (Fenster_OG_AZ.state == OPEN)
                        {
                        logInfo("Heizung", "Buero Heizung ist aus und Fenster wurde geöffnet")
                        }
        else
                if (Fenster_OG_AZ.state == CLOSED)
                        {
                        logInfo("Heizung", "Buero Heizung ist aus und Fenster wurde geschlossen")
                        Heizung_Buero_Setpoint.sendCommand(Heizung_Buero_Setpoint.historicState((Heizung_Buero_Zeitstempel.state as DateTimeType).getZonedDateTime()).state.toString)
                        logInfo("Heizung", "Heizung Büro wird auf den vorherigen Wert ("+ (Heizung_Buero_Setpoint.historicState((Heizung_Buero_Zeitstempel.state as DateTimeType).getZonedDateTime()).state.toString) +") gesetzt.")
                        Heizung_Buero_Zeitstempel.postUpdate(new DateTimeType(now.plusSeconds(1)))
                        if(timer_buero !== null)
                                {
                                timer_buero.cancel()
                                timer_buero = null
                                }
                        }
end

This is the entry for the state in the .items file:

String Heizung_Buero_Zeitstempel "Zeitstempel"