[SOLVED] Using A Variable To Obtain An Item State


I’m trying to create a rule to calculate a value from two items and post that value to a third item…

The two initial items are both defined as numbers as below with the third item also a number…

Number	SERVER1_Swap_Total
		"Swap Memory Total [%d]"

Number	SERVER1_Swap_Available
		"Swap Memory Available [%d]"

Number	SERVER1_Swap_Used
		"Swap Memory Used [%d]"

And the rule to perform the calculation and update the third item is as below…

rule "Swap Used Calculation"
        Member of fgSwapAvailable changed
        var Host = triggeringItem.name.split("_").get(0)
        var Total = Host + "_Swap_Total"
        var SwapUsed = ((Total).state as Number) - (triggeringItem.state as Number)
        logInfo("SNMP", triggeringItem.name + " - " + Host + " - " + Total)

Essentially, the triggering item should contain something like SERVER1_Swap_Available. The first var (Host) splits the triggering item on the _ character and correctly sets the variable Host to SERVER1. The second var (Total) is then set to the string SERVER1_Swap_Total and I’m trying to use this string as the item to obtain a state to perform a calculation, store the result of that calculation in a third variable and then post that value to the state of an item called SERVER1_Swap_Used with the SERVER1 element being the string contained in the Host variable.

Any ideas if this is even possible?

import org.eclipse.smarthome.model.script.ScriptServiceUtil

rule "Swap Used Calculation"
        Member of fgSwapAvailable changed
        val String Host = triggeringItem.name.split("_").get(0)

        val Total = ScriptServiceUtil.getItemRegistry.getItem(Host + "_Swap_Total")
        val SwapUsed = (Total.state as Number) - (triggeringItem.state as Number)
        logInfo("SNMP", triggeringItem.name + " - " + Host + " - " + Total.name.toString)
1 Like

Yes this is possible, please take a look at this very educative Design pattern of @rlkoshak:

Based on this, I use something like this myself:

val name = triggeringItem.name.split("_").get(0)
val setpoint = AllThermostatSetpoints.members.findFirst[ t | t.name == name + "_SetpointHeat" ] as NumberItem
val temp = AllThermostats.members.findFirst[ t | t.name == name + "_CurrentTemperature" ] as NumberItem
val mode = AllThermostatModes.members.findFirst[ t | t.name == name + "_ThermostatMode"] as NumberItem

So for example I have a rule which is triggered when Member of AllThermostatSetpoints changed or Member of AllThermostats changed, and all items in these groups have a name like Thermostat1_SetpointHeat or Thermostat_CurrentTemperature, respectively.
So the first line gets the base name, so “Thermostat1” in this example. Then setpoint finds the item Thermostat1_SetpointHeat, so that holds that item, and so on.
Subsequently you can use setpoint.state to get the value of the setpoint item, mode.sendCommand to set the value of the Thermostat1_ThermostatMode item, and so on.

Essential in this approach is that all _SetpointHeat items are in the same AllThermostatSetpoints group, and so on.

EDIT: @vzorglub beat me to it, with another nice approach, which might also be more efficient in this case.

1 Like

I would have pointed to that DP but it’s only worth it when dealing with several items in the same rule
Are we are only dealing with one in this case, it is simpler to use ScriptServiceUtil.getItemRegistry.getItem(

Thanks for the advice… However, when I enter this in VSCode I get an error stating

The method or field Host_Swap_Used is undefined

For the line



Do you have an item called Host_Swap_Used ?
Or should it be something else?

The “Host” portion is the string previously obtained with the

val String Host = triggeringItem.name.split("_").get(0)


Then instead of Host_Swap_Used you should use the same method @vzorglub showed for that one as well:

val Host_Swap_Used = ScriptServiceUtil.getItemRegistry.getItem(Host + "_Swap_Used")

Use a postUpdate instead as there are no bindings involved:


The trick is that you cannot just make up a string like “myItem” and expect the rules interpreter to understand it’s supposed to mean ‘find an Item with name’. Why wouldn’t you be putting it in a message for example; it’s just a string.

So in order to get hold of an actual Item called by “string” name, you need to use a method to find and retrieve that Item - if it exists. Once you’ve got the Item you can look at it’s state, send commands etc.
There’s a couple of non-obvious ways to do that, shown already.

Thanks all for the assistance… All is working properly now…

Please tick the solution post, thanks