Get itemname from a string

I stuck hardly and my knowledge in programming are poor.
So I have a simple rule and I have a string of which content I want to compare with items .
The goal is: Create the string, find the item , postUdate an item with the item state
import javax.swing.plaf.nimbus.State

rule “Sonoff_Maintenance"
when
Item send received command
then
var String temp10=”“
var String temp11=”"

   switch (sonoff_com.state) {
   case "restart":{
   publish ("broker","cmnd/"+sonoff_ID.state.toString+"/restart","1")
   }
   case "status":{
     publish ("broker","cmnd/"+sonoff_ID.state.toString+"/status","5")
     temp10=sonoff_ID.state.toString+"_statusALL"
     logInfo("Sonoff_Maintenance",temp10)
     temp11=(sonoff_ID.state.toString+"_status")

//temp11 is my string and I know that the content macht with one item at a time
logInfo(“Sonoff_Maintenance”,temp11)
//and here I tried to find the item from the group maint
//error "Cannot refer to the non-final variable temp11 inside a lambda expression"
var temp12 = maint.members.findFirst[name.equals(temp11)] as State< // and I am not sure about this "State"
sonoff_t_2_statusALL.postUpdate(temp12)
}
}
send.postUpdate(NULL)
end

Please someone help me…
Thnx in advance

Please use code fences for posting code in the forum.

```
code goes here
```

Please post your relevant Item definitions as well.

Issues I see from a quick scan:

  • You are comparing sonoff_com.state to Strings in the case statements. You probably have to use .toString

    switch(sonoff_com.state.toString)

  • Your Items and variables are rather poorly named. A good variable name should indiciate what it is for by its name. tmpe10 tells me nothing. Item names should indicate what they are. sonoff is a poor name. BedroomLamp is a better name as it is clear what you are controlling.

  • This may be the forum’s doing but you have a mixture of smart quotes (” “) and normal quotes (" ") in the code above. You cannot use smart quotes in Rules.

  • Similarly, this may be a side effect of the lack of code fences, but your indentation is not standard. By convention one always indents when you are introducing a new context. The easiest way to tell you are introducing a new context is when you see {. You code would be easier to read and understand with:

then
    var String temp10=""
    var String temp11=""

    switch(sonoff_com.state.toString){
        case "restart": {
            publish("broker", "cmd/"+sonoffID.state.toString+"/restart", "1")
        }
        ...
    }
  • I don’t understand why you have the parens around the String you assign to temp11

  • Your findFirst line is not right.

    var temp12 = maint.members.findFirst[i | i.name == temp11] as GenericItem

  • You cannot postUpdate an Item to another Item. If you want to postUpdate the state of the Item named with the String assigned to temp11 use:

    sonoff_t_2_statusALL.postUpdate(temp12.state)

  • You might not be able to postUpdate(NULL). There was another thread about that today. Though I’d love to know if it works.

  • What the heck are you importing something from swing?

A little more description about what this rule is supposed to do and the associated Items would be helpful because as it is posted, without more context, it is all but impossible to understand what it is supposed to do.

1 Like

Sonoff.items

//Online-Offline Status
String sonoff_b_1_status " [%s]" (status)  { mqtt="<[broker:tele/sonoff_b_1/LWT:command:default]" }
String sonoff_t_2_status  " [%s]" (status)  { mqtt="<[broker:tele/sonoff_t_2/LWT:command:default]" }
String sonoff_t_7_status  " [%s]" (status)  { mqtt="<[broker:tele/sonoff_t_7/LWT:command:default]" }
//...(and more)
//IPAddress Status
String sonoff_b_1_statusIP " [%s]" (IP) { mqtt="<[broker:stat/sonoff_b_1/STATUS5:command:default]" }
String sonoff_t_2_statusIP  " [%s]" (IP) { mqtt="<[broker:stat/sonoff_t_2/STATUS5:command:default]" }
String sonoff_t_7_statusIP  " [%s]" (IP) { mqtt="<[broker:stat/sonoff_t_7/STATUS5:command:default]" }
//...(and more)
//StatusALL Status
String sonoff_b_1_statusALL  " [%s]" (maint)
String sonoff_t_2_statusALL  " [%s]" (maint)
String sonoff_t_7_statusALL  " [%s]" (maint)
//...(and more)

//Maintenance 
String sonoff_com 
String sonoff_ID
Switch send
Group maint

settings.sitemap

sitemap settings label="Settings" {
    
    Frame label="Maintenance" {
        Selection item=sonoff_com label="Item C." icon="house" mappings=[
            "restart"="Restart",
            "status"="Status",
            "timezone"="Set timezone"]
            
        Selection item=sonoff_ID label="Item ID" icon="house" mappings=[
        "sonoff_t_2"="Κουζίνα",
        "sonoff_t_7"="Μπ. Σαλόνι",
        "sonoff_t_1"="Μπ. Κουζίνα",
//...(and more)
        Switch item=send   label="Execute" icon="house" mappings=[ON ="Send"]
    }

	Frame label= "Status lights"               {
	   Text item= sonoff_t_2_statusALL       label="Κουζίνα" icon="status" 
          Text item= sonoff_t_9_statusALL       label="Σαλόνι" icon="status"
          Text item= sonoff_t_4_statusALL       label="Δωμάτιο PC" icon="status"
      //...(and more)
		      	   					 }

and my rule

rule "Sonoff_Maintenance"
when
    Item send received command
then 
    var String  itemnamestrAll=""
    var String  itemnamestrstat=""
    var String  itemnamestrIP=""
       switch (sonoff_com.state) {
       case "restart":{
       publish ("broker","cmnd/"+sonoff_ID.state.toString+"/restart","1")
       }
       case "status":{
         publish ("broker","cmnd/"+sonoff_ID.state.toString+"/status","5")
         itemnamestrAll=sonoff_ID.state.toString+"_statusALL"
         itemnamestrstat=sonoff_ID.state.toString+"_status"
         itemnamestrIP=sonoff_ID.state.toString+"_statusIP"
         var itemnameALL  = maint.members.findFirst[i | i.name == itemnamestrAll] as GenericItem
//The only error appears : Cannot refer to the non-final variable itemnamestrAllinside a lambda expression
         var itemnamestat = status.members.findFirst[i | i.name == itemnamestrstat] as GenericItem
//The only error appears : Cannot refer to the non-final variable itemnamestrstatinside a lambda expression
         var itemnameIP   = IP.members.findFirst[i | i.name == itemnamestrIP] as GenericItem
//The only error appears : Cannot refer to the non-final variable itemnamestrIPinside a lambda expression
         itemnameALL.postUpdate(itemnamestat.state+" "+itemnameIP.state)
                }
       }
       send.postUpdate(OFF)
end 

The only error appears is in lines above according to the find item from string
So rule tries to get from items info like LWT and IP that sonoffs send and put it in one item (Text ) side by side
(sorry for my English)

 var String  itemnamestrAll
    var String  itemnamestrstat
    var String  itemnamestrIP

rule "Sonoff_Maintenance"
when
    Item send received command
then 
    
       switch (sonoff_com.state) {
       case "restart":{
       publish ("broker","cmnd/"+sonoff_ID.state.toString+"/restart","1")
       }
       case "status":{
         publish ("broker","cmnd/"+sonoff_ID.state.toString+"/status","5")
         createTimer(now.plusSeconds(2)) [|
         itemnamestrAll=sonoff_ID.state.toString+"_statusALL"
         itemnamestrstat=sonoff_ID.state.toString+"_status"
         itemnamestrIP=sonoff_ID.state.toString+"_statusIP"
         var itemnameALL  = maint.members.findFirst[i | i.name == itemnamestrAll] as GenericItem
         var itemnamestat = status.members.findFirst[i | i.name == itemnamestrstat] as GenericItem
         var itemnameIP   = IP.members.findFirst[i | i.name == itemnamestrIP] as GenericItem
         itemnameALL.postUpdate(itemnamestat.state.toString+" "+itemnameIP.state.toString.substring(57,69))
                  ]
                }
        case "timezone":{
        publish ("broker","cmnd/"+sonoff_ID.state.toString+"/Timezone","3")
        }
        case "Upgrade":{
        publish ("broker","cmnd/"+sonoff_ID.state.toString+"/OtaUrl","http://sonoff.maddox.co.uk/tasmota/sonoff.bin")
        createTimer(now.plusSeconds(2)) [|
        publish ("broker","cmnd/"+sonoff_ID.state.toString+"/upgrade","1")
                ]
         }
       }
       send.postUpdate(NULL)
end 

I did it. I had to put variables above the rule to define them as Global I guess.
Thnx for the info and the inspiration. I have to learn a lot of things

@hwa_rang098tkd could you please summarize what this “status” part does and why you need it?

All three are the same error.

Anytime you have [ | ] you have a lambda. So the findFirst[i | i.name == itemnamestrAll] is a lambda.

With few exceptions, the code inside a lambda cannot reference a non-final variable. A final variable is declared with val instead of var but a final variable is also unchangable.

There is absolutely no reason for you to declare the itemnamestr* at the top of the rule. They are only used in the “status” case and are only ever assigned a single usable value. So just use:

then 
       switch (sonoff_com.state) {
           case "restart":{
               publish ("broker","cmnd/"+sonoff_ID.state.toString+"/restart","1")
           }
           case "status":{
               publish ("broker","cmnd/"+sonoff_ID.state.toString+"/status","5")
               var itemnamestrAll = sonoff_ID.state.toString+"_statusALL"
               var itemnamestrstat = sonoff_ID.state.toString+"_status"
               var itemnamestrIP = sonoff_ID.state.toString+"_statusIP"
               var itemnameALL  = maint.members.findFirst[i | i.name == itemnamestrAll] as GenericItem
//The only error appears : Cannot refer to the non-final variable itemnamestrAllinside a lambda expression
               var itemnamestat = status.members.findFirst[i | i.name == itemnamestrstat] as GenericItem
//The only error appears : Cannot refer to the non-final variable itemnamestrstatinside a lambda expression
               var itemnameIP   = IP.members.findFirst[i | i.name == itemnamestrIP] as GenericItem
//The only error appears : Cannot refer to the non-final variable itemnamestrIPinside a lambda expression
               itemnameALL.postUpdate(itemnamestat.state+" "+itemnameIP.state)
           }
       }
       send.postUpdate(OFF)
end 
1 Like