Sure. In Java it’s called a Map but it’s the same thing. However, the Object you get for the Items when the rule runs is specially created for that rule and will become stale and disconnected from the “actual” Item at some point (e.g. if you reload your .items file). So it’s better to use the Item’s name instead of the actual Item Object.
import java.util.Map
import org.eclipse.smarthome.model.script.ScriptServiceUtil
val Map<String, String> plugMap = newHashmap("2002" -> "PhilipsHueSmartPlugCH1_Power",
"3002" -> "PhilipsHueSmartPlugCH2_Power",
"4002" -> "PhilipsHueSmartPlugDE1_Power")
val plug = ScriptServiceUtil.getItemRegistry.getItem(plugMap.get(IKEASTYRBAR_Button.state.toString))
plug.sendCommand(if(plug.state == ON) OFF else ON)
There are other approaches you could use too. For examples,
you could embed the number into the Item name of the plug. Put the plug into a Group and you could search the members for the Item that includes the number in the name.
val plug = Plugs.members.findFirst[ i | i.name.contains(IKEASTYRBAR_Button.state.toString)]
plug.sendCommand(if(plug.state == ON) OFF else ON)
you could use the Map transformation to map the button number with the Item name. The nice part about that is the mapping is separate from the rule so you can add/remove/change the mapping without touching the code
import org.eclipse.smarthome.model.script.ScriptServiceUtil
val plug = ScriptServiceUtil.getItemRegistry.getItem(transform("MAP", "plugs.map", IKEASTYRBAR_Button.state.toString))
plug.sendCommand(if(plug.state == ON) OFF else ON)
you could tag the Items with the button number and use itemRegistry.getItemsByTag(IKEASTYRBAR_Button.state.toString)
import org.eclipse.smarthome.model.script.ScriptServiceUtil
val plug = ScriptServiceUtil.getItemRegistry.getItemsWithTag(IKEASTYRBAR_Button.state.toString).get(0)
plug.sendCommand(if(plug.state == ON) OFF else ON)
the other rules languages have a more complete set of programming language features than Rules DSL, using one of those might be a more natural fit.
Thank you so much for your detailed answer! But I was to quick in marking it as solution because now the rule does nothing anymore - it looks like this:
That might be a limitation in Rules DSL Script Actions I think. It makes sense because in Rules DSL the imports have to be the first thing in the file before any code. By the time you get to a Rules DSL Script Action, you are well past that context.
So you’ll either have to write this in a .rules file or you’ll have to use one of the other approaches that do not require imports (or use a different language like JS Scripting or jRuby which support dicts natively and even if they didn’t you can import anywhere in the code, not just at the top like in Rules DSL).
Which JavaScript did you switch over to? If ECMAScript 5.1 (Nashorn), keep in mind that version of JavaScript was released more than a decade ago. Map and a whole host of stuff you might expect to be there wasn’t part of the language yet for that version.
The JS Scripting add-on provides ECMAScript 2021 in a Node like environment (not completely Node like but close enough that most node libraries will work). If you want to use a modern version of JavaScript install the add-on and be sure to reference the add-on’s docs which have reference docs for the library to make interacting with OH easier from rules using pure JavaScript instead of needing to switch between Java Objects and JavaScript and keep track of what is what.