[SOLVED] Build a dynamic group with GroupItem Methods and send a command to this dynamic group

Hi there,

i was thinking about a way to create a dynamic group to play something on the TTS channel of every Alexa but not on the one i´m talking to.
The idea was to use the GroupItem Methods described by @rlkoshak in his thread Design Pattern: Working with Groups in Rules

The trigger is pretty easy but i´m currently not able to use the information returned by the method MyGroup.members.filter[ i | <condition> ]

Items

String echoFlur_lVC "Letztes Kommando [%s]" (Alexa_Flur, EchoCommands, Flur) {channel="amazonechocontrol:echo:Michael:echoFlur:lastVoiceCommand"}
String echoArbeitszimmer_lVC "Letztes Kommando [%s]" (Alexa_Arbeit, EchoCommands, Arbeit) {channel="amazonechocontrol:echo:Michael:echoArbeit:lastVoiceCommand"}
String echoWohnzimmer_lVC "Letztes Kommando [%s]" (Alexa_Wohnen, EchoCommands, Wohnen) {channel="amazonechocontrol:echo:Michael:echoWohnen:lastVoiceCommand"}
String echoKueche_lVC "Letztes Kommando [%s]" (Alexa_Kueche, EchoCommands, Kueche) {channel="amazonechocontrol:echo:Michael:echoKueche:lastVoiceCommand"}
rule "i need help"

when

    Member of EchoCommands changed to "i need help"

then

    val SourceEcho = triggeringItem.name.split("_").get(0)
    val SourceRoom = SourceEcho.removeStart("echo")
    val SourceRoomTTS = SourceRoom + "_TTS"
    val Message = "Could you please help me in the " + sourceRoom

    EchoCommands.members.filter[i | i.state != 'i need help' ].forEach[ i | sendCommand( i.name.replace("_lVC", "")+"_TTS", Message) ]
    SourceRoomTTS.sendCommand("I called all echos for help!")

    EchoCommands.members.forEach[ i | i.postUpdate('')]

end

Is this even possible?
Is there any other way to achieve this?

kind regards
Michael

  • Platform information:
    • Hardware: Raspberry Pi 3B
    • OS: raspbian 9 stretch
    • Java Runtime Environment:
      • openjdk version “1.8.0_152”
      • OpenJDK Runtime Environment (Zulu Embedded 8.25.0.76-linux-aarch32hf)
      • OpenJDK Client VM (Zulu Embedded 8.25.0.76-linux-aarch32hf)
    • openHAB version: 2.4.0-1 (Release Build)

This seems possible and a reasonable approach.

The only problem with it as implemented is filter returns a List, not a GroupItem. You can only send a command to an Item. You have to iterate over the List and send command to each member individually.

OtherRooms.forEach[i | i.sendCommand(Message)]

If you need to filter out more than just the source item just add more conditions to your filter. If EchoCommands contains associated items but not the ones you need to sendCommand to, then one can ask why don’t you have a group for the TTS Items? Failing that, just use the send Command Action in the forEach.

OtherRooms.forEach[i | sendCommand(i.name+"_TTS", Message)]

You do not and probably should not create a new dynamic group for this purpose.

1 Like

That´s what i was struggling with :slight_smile:

This should work fine as i´m always clearing the lastVoiceCommand at the end of rules and other Alexa commands shouldn´t contain this string i´m searching for.

There´s a group for ALL TTS items but not subgroups for every possible pairing.

How do i remove the _lVC part from every item in the list?

Thanks Rich!

in the forEach call use

i.name.replace("_lVC", "")
1 Like

I tried the following but oH throws an error.

val OtherRooms = EchoCommands.members.filter[i | i.state != 'i need help']
val OtherRoomsTTS = OtherRooms.forEach[i | i.name.replace("_lVC", "")]
OtherRoomsTTS.forEach[i | sendCommand(i.name+"_TTS", Message)]
2019-01-06 18:10:01.765 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Essen ist fertig': 'forEach' is not a member of 'Object'; line 16, column 5, length 60

And a small test shows that OtherRoomsTTS is empty.

logInfo("Test", "OtherRoomsTTS: " + OtherRoomsTTS)
2019-01-06 18:11:59.989 [INFO ] [.eclipse.smarthome.model.script.Test] - OtherRoomsTTS: null

It´s funny that the following works even though the text is send to the lastVoiceCommand channels!

val OtherRooms = EchoCommands.members.filter[i | i.state != 'i need help']
val OtherRoomsTTS = OtherRooms.forEach[i | i.name.replace("_lVC", "_TTS")]
OtherRoomsTTS.forEach[i | i.sendCommand(Message)]
2019-01-06 18:17:45.462 [INFO ] [.eclipse.smarthome.model.script.Test] - OtherRoomsTTS: null
2019-01-06 18:17:45.485 [ome.event.ItemCommandEvent] - Item 'echoFlur_lVC' received command Ich brauche Hilfe im Arbeitszimmer
2019-01-06 18:17:45.518 [ome.event.ItemCommandEvent] - Item 'echoWohnen_lVC' received command Ich brauche Hilfe im Arbeitszimmer
2019-01-06 18:17:45.535 [ome.event.ItemCommandEvent] - Item 'echoKueche_lVC' received command Ich brauche Hilfe im Arbeitszimmer
2019-01-06 18:17:45.543 [ome.event.ItemCommandEvent] - Item 'echoArbeit_TTS' received command Ich habe alle Echos zur Hilfe gerufen

One last hint @rlkoshak? :slight_smile:
Thanks!

I think you misunderstood. Put everything in the just one forEach. Your second line effectively does nothing because the replace doesn’t actually change the Item’s name, it returns the Items’s name with the requested modifications. You could do what you are after, but typically with streaming calls you do this all on one line which means you don’t have to.

EchoCommands.members.filter[i | i.state != 'i need help' ].forEach[ i | sendCommand( i.name.replace("_lVC", "")+"_TTS", Message) ]

That’s because forEach doesn’t return anything. It just iterates over the members of the List and does something with each member.

1 Like

Thanks alot Rich :slight_smile:

Working rule:

rule "i need help"

when

    Member of EchoCommands changed to "i need help"

then

    val SourceEcho = triggeringItem.name.split("_").get(0)
    val SourceRoom = SourceEcho.removeStart("echo")
    val SourceRoomTTS = SourceRoom + "_TTS"
    val Message = "Could you please help me in the " + sourceRoom

    EchoCommands.members.filter[i | i.state != 'i need help' ].forEach[ i | sendCommand( i.name.replace("_lVC", "")+"_TTS", Message) ]
    SourceRoomTTS.sendCommand("I called all echos for help!")

    EchoCommands.members.forEach[ i | i.postUpdate('')]

end