Hi everybody, I hope that somebody can help me. I’ve a rule which set lights in a group to the same value. That works fine. Now, I want to order the items in the group by their names to change the values in a special order. How can i get that?
var Collectors = Java.type("java.util.stream.Collectors");
var gNachtlichtAussen_Dimmer = ir.getItem("gNachtlichtAussen_Dimmer");
gNachtlichtAussen_Dimmer
.getAllMembers()
.stream()
.forEach(function(i){
events.sendCommand(i.name, ir.getItem("GartenbeleuchtungDimmer").getState());
logger.info(i.name);
java.lang.Thread.sleep(250);
});
for (gasPrice : gGasStationPrices.members.sortBy[ state as DecimalType ]) {
val String gasKey = gasPrice.name.substring(1, gasPrice.name.lastIndexOf('_'))
var ContactItem stationOpen = ScriptServiceUtil.getItemRegistry.getItem("i"+gasKey+"_Open") as ContactItem
var StringItem stationDisplay = ScriptServiceUtil.getItemRegistry.getItem("iSL_OH_GasStationItems_Display"+String::format("%02d", counter)) as StringItem
stationDisplay.setLabel(transform("MAP", "i18n_gasstation.map", gasPrice.name.substring(1, gasPrice.name.lastIndexOf('_'))))
if (stationOpen.state == OPEN) {
stationDisplay.postUpdate(String::format("%.3f €", (gasPrice.state as DecimalType).doubleValue()))
} else {
stationDisplay.postUpdate(transform("MAP", "i18n_contact.map", stationOpen.state.toString))
}
counter++
logInfo(ruleIdentifier, "Price for station {} processed.", gasKey)
}
When using the Java stream API like this you can use the sorted() method. However that will order them based on their “natural” order. I’m not sure that Items have a natural order. Try it and report back if.
NOTE: use the items dict.
var Collectors = Java.type("java.util.stream.Collectors");
var gNachtlichtAussen_Dimmer = ir.getItem("gNachtlichtAussen_Dimmer");
gNachtlichtAussen_Dimmer
.getAllMembers()
.stream()
.sorted()
.forEach(function(i){
events.sendCommand(i.name, items["GartenbeleuchtungDimmer"]);
logger.info(i.name);
java.lang.Thread.sleep(250);
});
If that doesn’t work you can create a Comparitor but it would probably be easier to use a map to get a list of just the Item names. Strings do have a natural order.
That only really exists in rules DSL unfortunately. In Nashorn JavaScript it’s easiest to use the Java Stream API. In Python it’s easiest to use Python native ways of managing lists and dicts.
Speaking of the streams API in Rules DSL, you could also implement your for loop as
gGasStationPrices.members
.sortBy[ state as Number] // Use Number instead of DecimalType, it avoids some problems
.forEach[ gasPrice |
val gasKey = gasPrice.name.... // Don't force the type unless you have to
var Collectors = Java.type("java.util.stream.Collectors");
var gNachtlichtAussen_Dimmer = ir.getItem("gNachtlichtAussen_Dimmer");
gNachtlichtAussen_Dimmer
.getAllMembers()
.stream()
.sorted()
.forEach(function(i){
events.sendCommand(i.name, items["GartenbeleuchtungDimmer"]);
logger.info(i.name);
java.lang.Thread.sleep(250);
});
That throws an exception:
Fail to execute action: 1
java.lang.ClassCastException: class org.openhab.core.library.items.DimmerItem cannot be cast to class java.lang.Comparable (org.openhab.core.library.items.DimmerItem is in unnamed module of
loader org.eclipse.osgi.internal.loader.EquinoxClassLoader @279a773a; java.lang.Comparable is in module java.base of loader 'bootstrap')