Problem with manipulating a string for a rule

Hi @ll,

atm i try to formate a message for my TelegramBot reply.
but it seems .replace() dont work in Rules?

rule “Report Temp by Telegram”
when
Item LastMessageText received update “Überblick”
then
//variable initialisieren
var String TempText = “”
//Telegram Bot Vorbereiten
val telegramAction = getActions(“telegram”,“telegram:telegramBot:86d92b46”)
// Soll Temp abholen
allTermostatSoll.members.forEach[item | TempText = TempText + item.name.replace(“Soll”,“Ist”) +"_Label : “+ item.name.replace(“Soll”,“Ist”) +”_State |"+ item.label + “: “+ item.state.toString +”\n”]
// Ist Temp ergänzen
allTermostatIst.members.forEach[item | TempText.replace(item.name+"_Label",item.label) logInfo(“TempTest”, item.name+"_Label") ]
allTermostatIst.members.forEach[item | TempText.replace(item.name+"_State",item.state.toString)]
//Nachricht versenden
telegramAction.sendTelegram(TempText)
logInfo(“TempTest”,TempText)
end

I thought it replaces the generated “Termostat_SZ_Temp_Ist_Label” with “item.label”

Can someone tell me where my fault is?

What does it do instead of what you expect?

Can’t really see what you are hoping to happen, much depends in Item names and Group memberships that we cannot see.
Break your code open a bit, step by step, and check values arewhat you expected. What is item.label? What is TempText?

Hi @rossko57,

the result is
Termostat_KA_Temp_Ist_Label : Termostat_KA_Temp_Ist_State |Katzenzimmer Soll Temperatur: 18.00 °C
Termostat_SZ_Temp_Ist_Label : Termostat_SZ_Temp_Ist_State |Schlafzimmer Soll Temperatur: 12.00 °C
Termostat_WZ_Temp_Ist_Label : Termostat_WZ_Temp_Ist_State |Wohnzimmer Soll Temperatur: 15.00 °C
Termostat_KU_Temp_Ist_Label : Termostat_KU_Temp_Ist_State |Küche Soll Temperatur: 18.00 °C
Termostat_BU_Temp_Ist_Label : Termostat_BU_Temp_Ist_State |Büro Soll Temperatur: 10.00 °C
Termostat_KZ_Temp_Ist_Label : Termostat_KZ_Temp_Ist_State |Kinderzimmer Soll Temperatur: 18.00 °C
Termostat_BR_Temp_Ist_Label : Termostat_BR_Temp_Ist_State |Bad Soll Temperatur: 17.00 °C

I expect:

Katzenzimmer Ist Temperatur : 18.00 °C |Katzenzimmer Soll Temperatur: 18.00 °C
Schlafzimmer Ist Temperatur: 12.00 °C |Schlafzimmer Soll Temperatur: 12.00 °C
Wohnzimmer Ist Temperatur: 15.00 °C  |Wohnzimmer Soll Temperatur: 15.00 °C
Küche Ist Temperatur: 18.00 °C |Küche Soll Temperatur: 18.00 °C
Büro Ist Temperatur: 10.00 °C |Büro Soll Temperatur: 10.00 °C
Kinderzimmer Ist Temperatur: 18.00 °C |Kinderzimmer Soll Temperatur: 18.00 °C
Bad Ist Temperatur: 17.00 °C |Bad Soll Temperatur: 17.00 °C

I try to describe what i wanna do

rule "Report Temp by Telegram"

when

    Item LastMessageText received update "Überblick"

then

    // prepare a empty var

    var String TempText = ""

    // Prepare the Telegram Bot

    val telegramAction = getActions("telegram","telegram:telegramBot:86d92b46")

    // get the "To" temperatures

    // allTermostatSoll

/*    

Group allTermostatSoll "Alle Termostate Soll zustand"                                                           [ "Thermostat", "Celsius" ]

Group allTermostatIst "Alle Termostate ist Zustand"                                                             [ "Thermostat", "Celsius" ]

Group gTermostat_WZ "Wohnzimmer Heizung"       <sofa>                                                           [ "Thermostat", "Celsius" ]

    String Termostat_WZ_Modus "Wohnzimmer Heating/Cooling Mode"                 (gTermostat_WZ)                 [ "HeatingCoolingMode" ]        {channel="homematic:HM-CC-RT-DN:3014F711A0001F58A9A70C4:KEQ072361:4#CONTROL_MODE"}

    Number:Temperature Termostat_WZ_Temp_Soll "Wohnzimmer Soll Temperatur"      (gTermostat_WZ,allTermostatSoll)        [ "TargetTemperature" ]         {channel="homematic:HM-CC-RT-DN:3014F711A0001F58A9A70C4:KEQ072361:4#SET_TEMPERATURE"}

    Number:Temperature Termostat_WZ_Temp_Ist "Wohnzimmer Ist Temperatur"        (gTermostat_WZ,allTermostatIst)         [ "CurrentTemperature" ]        {channel="homematic:HM-CC-RT-DN:3014F711A0001F58A9A70C4:KEQ072361:4#ACTUAL_TEMPERATURE"}

    

Group gTermostat_KU "Küche Heizung"   <kitchen>                                                                 [ "Thermostat", "Celsius" ]

    String Termostat_KU_Modus "Küche Heating/Cooling Mode"                      (gTermostat_KU)                 [ "HeatingCoolingMode" ]        {channel="homematic:HM-CC-RT-DN:3014F711A0001F58A9A70C4:KEQ072823:4#CONTROL_MODE"}

    Number:Temperature Termostat_KU_Temp_Soll "Küche Soll Temperatur"           (gTermostat_KU,allTermostatSoll)        [ "TargetTemperature" ]         {channel="homematic:HM-CC-RT-DN:3014F711A0001F58A9A70C4:KEQ072823:4#SET_TEMPERATURE"}

    Number:Temperature Termostat_KU_Temp_Ist "Küche Ist Temperatur"             (gTermostat_KU,allTermostatIst)         [ "CurrentTemperature" ]        {channel="homematic:HM-CC-RT-DN:3014F711A0001F58A9A70C4:KEQ072823:4#ACTUAL_TEMPERATURE"} 

*/

    // add a line with placeholder to TempText "Termostat_KA_Temp_Ist_Label : Termostat_KA_Temp_Ist_State |Katzenzimmer Soll Temperatur: 18.00 °C\n"

    allTermostatSoll.members.forEach[item | TempText = TempText + item.name.replace("Soll","Ist") +"_Label : "+ item.name.replace("Soll","Ist") +"_State |"+ item.label + ": "+ item.state.toString +"\n"]

 

    // Run a 2nd foreach to replace the placeholder "Termostat_KA_Temp_Ist_Label" with the value of "item.label"

    // item.name+"_Label" should be "Termostat_KA_Temp_Ist_Label"

    allTermostatIst.members.forEach[item | TempText.replace(item.name+"_Label",item.label) logInfo("TempTest", item.name+"_Label") ]

    allTermostatIst.members.forEach[item | TempText.replace(item.name+"_State",item.state.toString)]

    // Send the TempText as message

    telegramAction.sendTelegram(TempText)

    logInfo("TempTest",TempText)

end

I repeat, step by step. One big string at the end of the rule does not help you find out which step did not perform as you expected.
You have put some intermediate logging in, but kept the results secret.

For example, let’s expand

allTermostatIst.members.forEach[item | TempText.replace(item.name+"_Label",item.label) logInfo("TempTest", item.name+"_Label") ]

into

allTermostatIst.members.forEach[item |
   logInfo("test", "Step with Item " + item.name)
   logInfo("test". "Step starts with " + TempText)
   if (TempText.contains((item.name+"_Label") {
      logInfo("test", "replacing " + item.name + "_Label with " + item.label)
      TempText.replace(item.name+"_Label",item.label)
   } else {
      logInfo("test", "replacing fail " + item.name + "_Label")
   }
   ]

this wont work :frowning:

2020-09-13 21:10:30.108 [WARN ] [el.core.internal.ModelRepositoryImpl] - Configuration model ‘telegram.rules’ has errors, therefore ignoring it: [46,20]: no viable alternative at input ‘"Step starts with "’
[46,50]: mismatched input ‘)’ expecting ‘]’
[47,47]: mismatched input ‘{’ expecting ‘)’
[53,4]: mismatched input ‘]’ expecting ‘end’

Golly, I suppose you could fix it. There’s a stop . where there should be a comma ,

Thx for it, there was a second fault but i found. the Los is now a bit weird.

2020-09-13 21:21:35.148 [INFO ] [.eclipse.smarthome.model.script.test] - replacing Termostat_WZ_Temp_Ist_Label with Wohnzimmer Ist Temperatur
2020-09-13 21:21:35.158 [INFO ] [.eclipse.smarthome.model.script.test] - Step with Item Termostat_KU_Temp_Ist
2020-09-13 21:21:35.164 [INFO ] [.eclipse.smarthome.model.script.test] - Step starts with Termostat_KA_Temp_Ist_Label : Termostat_KA_Temp_Ist_State |Katzenzimmer Soll Temperatur: 18.00 °C
Termostat_SZ_Temp_Ist_Label : Termostat_SZ_Temp_Ist_State |Schlafzimmer Soll Temperatur: 12.00 °C
Termostat_WZ_Temp_Ist_Label : Termostat_WZ_Temp_Ist_State |Wohnzimmer Soll Temperatur: 15.00 °C
Termostat_KU_Temp_Ist_Label : Termostat_KU_Temp_Ist_State |Küche Soll Temperatur: 12.00 °C
Termostat_BU_Temp_Ist_Label : Termostat_BU_Temp_Ist_State |Büro Soll Temperatur: 10.00 °C
Termostat_KZ_Temp_Ist_Label : Termostat_KZ_Temp_Ist_State |Kinderzimmer Soll Temperatur: 18.00 °C
Termostat_BR_Temp_Ist_Label : Termostat_BR_Temp_Ist_State |Bad Soll Temperatur: 17.00 °C

2020-09-13 21:21:35.175 [INFO ] [.eclipse.smarthome.model.script.test] - replacing Termostat_KU_Temp_Ist_Label with Küche Ist Temperatur
2020-09-13 21:21:35.184 [INFO ] [.eclipse.smarthome.model.script.test] - Step with Item Termostat_SZ_Temp_Ist
2020-09-13 21:21:35.191 [INFO ] [.eclipse.smarthome.model.script.test] - Step starts with Termostat_KA_Temp_Ist_Label : Termostat_KA_Temp_Ist_State |Katzenzimmer Soll Temperatur: 18.00 °C
Termostat_SZ_Temp_Ist_Label : Termostat_SZ_Temp_Ist_State |Schlafzimmer Soll Temperatur: 12.00 °C
Termostat_WZ_Temp_Ist_Label : Termostat_WZ_Temp_Ist_State |Wohnzimmer Soll Temperatur: 15.00 °C
Termostat_KU_Temp_Ist_Label : Termostat_KU_Temp_Ist_State |Küche Soll Temperatur: 12.00 °C
Termostat_BU_Temp_Ist_Label : Termostat_BU_Temp_Ist_State |Büro Soll Temperatur: 10.00 °C
Termostat_KZ_Temp_Ist_Label : Termostat_KZ_Temp_Ist_State |Kinderzimmer Soll Temperatur: 18.00 °C
Termostat_BR_Temp_Ist_Label : Termostat_BR_Temp_Ist_State |Bad Soll Temperatur: 17.00 °C

2020-09-13 21:21:35.201 [INFO ] [.eclipse.smarthome.model.script.test] - replacing Termostat_SZ_Temp_Ist_Label with Schlafzimmer Ist Temperatur
2020-09-13 21:21:35.211 [INFO ] [.eclipse.smarthome.model.script.test] - Step with Item Termostat_KZ_Temp_Ist
2020-09-13 21:21:35.217 [INFO ] [.eclipse.smarthome.model.script.test] - Step starts with Termostat_KA_Temp_Ist_Label : Termostat_KA_Temp_Ist_State |Katzenzimmer Soll Temperatur: 18.00 °C
Termostat_SZ_Temp_Ist_Label : Termostat_SZ_Temp_Ist_State |Schlafzimmer Soll Temperatur: 12.00 °C
Termostat_WZ_Temp_Ist_Label : Termostat_WZ_Temp_Ist_State |Wohnzimmer Soll Temperatur: 15.00 °C
Termostat_KU_Temp_Ist_Label : Termostat_KU_Temp_Ist_State |Küche Soll Temperatur: 12.00 °C
Termostat_BU_Temp_Ist_Label : Termostat_BU_Temp_Ist_State |Büro Soll Temperatur: 10.00 °C
Termostat_KZ_Temp_Ist_Label : Termostat_KZ_Temp_Ist_State |Kinderzimmer Soll Temperatur: 18.00 °C
Termostat_BR_Temp_Ist_Label : Termostat_BR_Temp_Ist_State |Bad Soll Temperatur: 17.00 °C

2020-09-13 21:21:35.227 [INFO ] [.eclipse.smarthome.model.script.test] - replacing Termostat_KZ_Temp_Ist_Label with Kinderzimmer Ist Temperatur
2020-09-13 21:21:35.236 [INFO ] [.eclipse.smarthome.model.script.test] - Step with Item Termostat_BR_Temp_Ist
2020-09-13 21:21:35.242 [INFO ] [.eclipse.smarthome.model.script.test] - Step starts with Termostat_KA_Temp_Ist_Label : Termostat_KA_Temp_Ist_State |Katzenzimmer Soll Temperatur: 18.00 °C
Termostat_SZ_Temp_Ist_Label : Termostat_SZ_Temp_Ist_State |Schlafzimmer Soll Temperatur: 12.00 °C
Termostat_WZ_Temp_Ist_Label : Termostat_WZ_Temp_Ist_State |Wohnzimmer Soll Temperatur: 15.00 °C
Termostat_KU_Temp_Ist_Label : Termostat_KU_Temp_Ist_State |Küche Soll Temperatur: 12.00 °C
Termostat_BU_Temp_Ist_Label : Termostat_BU_Temp_Ist_State |Büro Soll Temperatur: 10.00 °C
Termostat_KZ_Temp_Ist_Label : Termostat_KZ_Temp_Ist_State |Kinderzimmer Soll Temperatur: 18.00 °C
Termostat_BR_Temp_Ist_Label : Termostat_BR_Temp_Ist_State |Bad Soll Temperatur: 17.00 °C

2020-09-13 21:21:35.250 [INFO ] [.eclipse.smarthome.model.script.test] - replacing Termostat_BR_Temp_Ist_Label with Bad Ist Temperatur
2020-09-13 21:21:35.258 [INFO ] [.eclipse.smarthome.model.script.test] - Step with Item Termostat_KA_Temp_Ist
2020-09-13 21:21:35.263 [INFO ] [.eclipse.smarthome.model.script.test] - Step starts with Termostat_KA_Temp_Ist_Label : Termostat_KA_Temp_Ist_State |Katzenzimmer Soll Temperatur: 18.00 °C
Termostat_SZ_Temp_Ist_Label : Termostat_SZ_Temp_Ist_State |Schlafzimmer Soll Temperatur: 12.00 °C
Termostat_WZ_Temp_Ist_Label : Termostat_WZ_Temp_Ist_State |Wohnzimmer Soll Temperatur: 15.00 °C
Termostat_KU_Temp_Ist_Label : Termostat_KU_Temp_Ist_State |Küche Soll Temperatur: 12.00 °C
Termostat_BU_Temp_Ist_Label : Termostat_BU_Temp_Ist_State |Büro Soll Temperatur: 10.00 °C
Termostat_KZ_Temp_Ist_Label : Termostat_KZ_Temp_Ist_State |Kinderzimmer Soll Temperatur: 18.00 °C
Termostat_BR_Temp_Ist_Label : Termostat_BR_Temp_Ist_State |Bad Soll Temperatur: 17.00 °C

2020-09-13 21:21:35.272 [INFO ] [.eclipse.smarthome.model.script.test] - replacing Termostat_KA_Temp_Ist_Label with Katzenzimmer Ist Temperatur
2020-09-13 21:21:35.287 [INFO ] [.eclipse.smarthome.model.script.test] - Step with Item Termostat_BU_Temp_Ist
2020-09-13 21:21:35.292 [INFO ] [.eclipse.smarthome.model.script.test] - Step starts with Termostat_KA_Temp_Ist_Label : Termostat_KA_Temp_Ist_State |Katzenzimmer Soll Temperatur: 18.00 °C
Termostat_SZ_Temp_Ist_Label : Termostat_SZ_Temp_Ist_State |Schlafzimmer Soll Temperatur: 12.00 °C
Termostat_WZ_Temp_Ist_Label : Termostat_WZ_Temp_Ist_State |Wohnzimmer Soll Temperatur: 15.00 °C
Termostat_KU_Temp_Ist_Label : Termostat_KU_Temp_Ist_State |Küche Soll Temperatur: 12.00 °C
Termostat_BU_Temp_Ist_Label : Termostat_BU_Temp_Ist_State |Büro Soll Temperatur: 10.00 °C
Termostat_KZ_Temp_Ist_Label : Termostat_KZ_Temp_Ist_State |Kinderzimmer Soll Temperatur: 18.00 °C
Termostat_BR_Temp_Ist_Label : Termostat_BR_Temp_Ist_State |Bad Soll Temperatur: 17.00 °C

2020-09-13 21:21:35.301 [INFO ] [.eclipse.smarthome.model.script.test] - replacing Termostat_BU_Temp_Ist_Label with Büro Ist Temperatur
2020-09-13 21:21:35.682 [INFO ] [ipse.smarthome.model.script.TempTest] - Termostat_KA_Temp_Ist_Label : Termostat_KA_Temp_Ist_State |Katzenzimmer Soll Temperatur: 18.00 °C
Termostat_SZ_Temp_Ist_Label : Termostat_SZ_Temp_Ist_State |Schlafzimmer Soll Temperatur: 12.00 °C
Termostat_WZ_Temp_Ist_Label : Termostat_WZ_Temp_Ist_State |Wohnzimmer Soll Temperatur: 15.00 °C
Termostat_KU_Temp_Ist_Label : Termostat_KU_Temp_Ist_State |Küche Soll Temperatur: 12.00 °C
Termostat_BU_Temp_Ist_Label : Termostat_BU_Temp_Ist_State |Büro Soll Temperatur: 10.00 °C
Termostat_KZ_Temp_Ist_Label : Termostat_KZ_Temp_Ist_State |Kinderzimmer Soll Temperatur: 18.00 °C
Termostat_BR_Temp_Ist_Label : Termostat_BR_Temp_Ist_State |Bad Soll Temperatur: 17.00 °C

Okay, so it clearly shows the replace does not work. Or rather, the string that the replace operates on does not survive outside of the [ ] lambda.

This is one of those things about passing variables out of lambdas, basically you can’t. So each iteration of the forEach gets the unaltered ‘outside’ version of the string.

The basic problem is tackled here - use of StringBuilder allows appending within a lambda.


however I’m not sure what you should do to edit a pre-existing string within a lambda.

Are you filtering the logs here? I’m surprised it is not complaining about ‘non-final variables’

Okay, spent some time on this.

You have a group of Items Termostat_xxx_Ist, each of which has a counterpart Termostat_xxx_Soll

You want to produce some text for this set like
" xxx ist-label : 12.00 °C | xxx soll-label : 18.00 °C
yyy ist-label : 15.00 °C | yyy soll-label : 16.00 °C"

Let’s not mess with placeholder text, just do it directly using method from here
Design Pattern: Associated Items.

   // make a stringy object val that we can still append to
val StringBuilder myMessage = new StringBuilder
   // iterate through "Ist" Items
allTermostatIst.members.forEach[ist |
      // add label text
    myMessage.append(ist.label + " : ")
      // add state
   myMessage.append(ist.state.toString + " | ")
      // work out partner Item name
   val sollName = ist.name.replace("_Ist", "_Soll")
      // get partner Item from its group
   val soll = allTermostatSoll.members.findFirst[ a | a.name == sollName]
   if (soll === null) {
         // surprise
      myMessage.append("Missing Soll Item " + sollname)
   } else {
         // now do soll label and value
      myMessage.append(soll.label + " : ")
      myMessage.append(soll.state.toString + "/n")
   }
]
   // all done
telegramAction.sendTelegram(myMessage)

thank you so much @rossko57 this works great.
Now i will see how i can use it for other things too :slight_smile: