Well, it’s only an example, you’ll probably need to work your own up. But -
This wrong format. The (groups) need to be placed before the {bindings}.
It’s always been that way, but I expect the Items file parser has incorporated more checks since 2017
Thank you for pointing out the errors. As rossko57 points out, the example never was intended to be copied from the posting and used. It shows how to use the operations discussed but you would be expected to apply those operations to your own Items and Groups.
In some cases, there are better ways to achieve the same thing, sometimes without Rules at all, e.g. there is a Profile to update the LastUpdate Items.
Please don’t double post. I’ve answered on the other thread.
A DP is a general and reusable solution to a common problem. But the solution is not complete. Instead it is a template that one can apply to a lot of different situations with minor modifications and customizations.
This particular DP is also a little different and probably should never have been a DP in the first place. Frankly, what it is is some reference documentation missing from the Xtend docs for how to manipulate collections. It’s not so much a DP as it is a reference guide. As such, the example is just that, and example. It was never intended to be something someone copies and uses line for line. Some of the other DPs do in fact have examples that could be copied and used line for line though, assuming that the example is useful to you. But even then it is unlikely to be useful “out-of-the-box”. The examples are there to illustrate how to solve a common problem. Rarely will you find any example on the forum, DP or otherwise, that you can just use without modification.
The example above though is mainly for illustrative purposes, to show some of those operations in context. That’s probably why the errors you found haven’t been found by others in the three + years this DP has been posted.
I thought I’d share my code for simulating a time of day type of expire based on groups. Essentially, any member of this group will stay on for an hour if it is turned on between 6am and 11pm; they will only stay on for 30 minutes from 11pm to 6am, though (family is more likely to have fallen asleep…)
I pieced this together mostly from other blocks of code in this thread so credit goes to those guys for blazing the trail. If you have a sizable number of items this beats having lots of rules that all basically do the same thing. It would be trivial to extend this to another group that would have different times as well.
First – groups and items::
Group grp_TODExpire "Expire by Time of Day"
Dimmer Wallplug_Den_BigLamp "Den Lamp" <dimmablelight> (grp_TODExpire) { channel="zwave..." }
Dimmer WallSwitch_Den_CeilLight "Ceiling Light" <dimmablelight> (grp_TODExpire) { channel="zwave..." }
Now the rule:
off_tod.rule
import java.util.Map
val Map<String, Timer> todTimers = newHashMap
rule "TOD Expire rule"
when
Member of grp_TODExpire changed
then
logInfo("RULE","Item "+triggeringItem.name+" turned "+triggeringItem.state+".");
todTimers.get(triggeringItem.name)?.cancel;
if (triggeringItem.state==ON || triggeringItem.state>0) {
if ((new LocalTime().getLocalMillis()) >= (new LocalTime(23, 0, 0, 0).getLocalMillis()) || (new LocalTime().getLocalMillis()) <= (new LocalTime(6, 0, 0, 0).getLocalMillis())) {
logInfo("RULE","Item "+triggeringItem.name+" turned on. Will turn it off in 30 minutes");
todTimers.put(triggeringItem.name, createTimer(now.plusMinutes(30)) [|
sendCommand(triggeringItem, OFF)
todTimers.remove(triggeringItem.name)
] )
} else {
logInfo("RULE","Item "+triggeringItem.name+" turned on. Will turn it off in 60 minutes");
todTimers.put(triggeringItem.name, createTimer(now.plusMinutes(60)) [|
sendCommand(triggeringItem, OFF)
todTimers.remove(triggeringItem.name)
] )
}
}
end
when
OG_Wohnzimmer_Motion_Occupancy changed from OFF to ON
then
if (OG_Wohnzimmer_Tuer_Power.state.toString == “OFF” && OG_Wohnzimmer_Sofa_Power.state.toString == “OFF”) {
and would like change the if clause to check the state of the group of the items. How do I do this?
Hi,
I’m trying to get a complete local copy from a group item in a rule so I can perform operations on this group without affecting the global group in my item file.
I tried several ways to get copies of my group item but none of was working.
So I tried filtering the group item and assigning it to a new variable like it could be done with findFirst but that didn’t work either and unfortunately I couldn’t find any working example.
(the following code is not working but they were part of my journey on the way to despairing )
val GroupItem sceneItems = Scene_Items.members
val sceneItems = Scene_Items.members.filter[ grp | grp.name.contains(itemNamePrefix+sceneRoomString) ]
So as I spent many hours with kind of trial and error without any success I’d like to ask you if you know any solution for my problem.
This should work fine, as long as all of the members of Scene_Items are groups, although sceneItems is not a GroupItem but Iterable. You can’t create an Item in the rules DSL… you’d need scripted automation for that. The Jython helper libraries make this easier.
val sceneItems = Scene_Items.members.filter[GroupItem group | group.name.contains(itemNamePrefix + sceneRoomString)]
What errors are you getting? It is much better to describe what you would like to do, rather than ask for help on how to implement a particular solution. There may be easier ways to do what you are trying to accomplish. Take a look at #8.
For example, this may provide everything you’re looking to implement…
I think that is what I unintentionally tried to do.
For now I created a new group item in an items file and this group item gets cleared every time I call the rule so I can then add new members from my ‘Scene_Items’ group. This solves my problem for now but I think in the long run I have to (and will) make use of the Jython helper libraries you mentioned.
i try to simplify my rules for the OpenSprinkler Telegram rules i wrote to get the label names from the items file… and also to get the buttons in the amount of stations that are not OFF
OLD part:
val OSPI_ReplyId = "OSPI_Reply"
var StationDuration = 600 // 10min
val Station01 = "Rasen oben"
val Station02 = "Rasen Hang"
val StationOFF = "Alle aus"
rule "Telegram Bot receive rasen"
when
Item TelegramBotLastMessageDate received update
then
val telegramAction = getActions("telegram","telegram:telegramBot:bot1")
if (TelegramBotLastMessageText.state.toString.toLowerCase == "/rasen") {
telegramAction.sendTelegramQuery(Long::parseLong(TelegramBotChatId.state.toString), "*Beregnungs-Optionen:*\nWelcher Bereich soll bewässert werden?", OSPI_ReplyId, Station01, Station02, StationOFF)
}
end
New Part:
val OSPI_ReplyId = "OSPI_Reply"
var StationDuration = 600 // 10min
val StationOFF = "Alle aus"
rule "Telegram Bot receive rasen"
when
Item TelegramBotLastMessageDate received update
then
val telegramAction = getActions("telegram","telegram:telegramBot:bot1")
val reply_text = "*Beregnungs-Optionen:*\nWelcher Bereich soll bewässert werden?"
val reply_buttons = gOSPI_Station.members.filter[ i | i.state == OFF ].map[ label ]
logInfo("OSPI_Reply", reply_buttons.toString)
if (TelegramBotLastMessageText.state.toString.toLowerCase == "/rasen") {
telegramAction.sendTelegramQuery(Long::parseLong(TelegramBotChatId.state.toString), reply_text, OSPI_ReplyId, reply_buttons)
}
end
Now here comes the part where i could need some help…
the reply_buttons i generated in the correct amount of stations… and for each name it is created the button in the telegram chat…
Now i want to add the val StationOFF to that String so that this button is also generated…
any tips on how to achieve that?
One approach could be to create a dummy item and also add it to the group gOSPI_Station, but i want to avoid that.
I’m not entirely certain what you are asking for here. I don’t use Telegram so don’t have a context. Are you asking to have two strings for each station, one to turn it on and one to turn it off?
If so you probably can’t use the map and instead need to use a for loop to build up the List manually.
val reply_buttons = newArrayList
gOSPI_Station.members.filter[ i | i.state == OFF ].forEach[ s |
reply_buttons.add(s.label)
reply_buttons.add(s.label + " OFF")
]
my line val reply_buttons = gOSPI_Station.members.filter[ i | i.state == OFF ].map[ label ]
is resluting in this 2020-08-19 18:07:31.988 [INFO ] [se.smarthome.model.script.OSPI_Reply] - [Station 1, Station 2]
Station 1, Station 2 are the labels of current gOSPI_Station members (which will be more in the future)
and beside these Station names… I also want to append the String with “All OFF”