How to select an element from an array?

Hi everybody,

I’m trying to figure out how to convert an array of selected modes in preferences into several variables, one for each item of the array.

If anyone feels like helping on this. So far I’ve only succeeded in determining how many modes were selected by the user, but I also need to set different settings for each one of these modes so I would like to “transform”, for instance, an array of 3 modes into 3 separate values, using each mode’s index position.

Thanks in advance!
Elfege

Def element0 = list [0] if I recall…

1 Like

yes! Thanks a lot! :smiley:

While we’re at it… :slight_smile: Maybe you can help me a little further :slight_smile:

I have a set of 4 variables such as “state.T1_variable” , “state.T2_variable” , and so on.
each one corresponding to the state of a thermostat

Now, I have a handler that will recognize which thermostat is the source, so far so good.

But I want to do this :

for an array like :

def array = [“state.T1_variable” , “state.T2_variable” … and so on]

let’s say currently we have these values for this list of variables:
state.T1_variable = 0
state.T2_variable = 1

def number = 2 // this is declared by the event, thermostat 2 is the device (set by another array somewhere else in my code)
so we know that the variable we will change is number 1 in the array, that is:

def VariableToChange = array[number]

Here is my question:

Is there a way to change the value of the original variable ?

I mean I want something like this:
state.T[number]_variable = 0

so now in other loops the variable state.T2_variable doesn’t return 1 but 0…

for now I’m using endless series of if and something tells me there must be a shorter way… any idea?

Thanks (a lot!) in advance!
Elfege

Many ways to do that, so here’s one.
State.tList = state.tList ?: [0,0,0,0] //init with default values if null
State.tList [0] = newValue

State.tList [3] = newValue
Def temp = state.tList [2]
Etc…

There are more elegant ways of doing it as well, adding them as needed as an example.
You want to bone up on groovy list and map data structures, all of which can be stored and retrieved within state objects.

Thank you! This actually put me on the right track!

One more question, if I may take too much advantage of your kindness @Mike_Maxwell : I am now trying to figure out how to extract the index value of an item in an array.

I have a list of 4 modes in an array and thanks to your advice I was able to extract the current location mode from it. Now I need to make it correspond to a variable declaring its index number value.

Again, many thanks for your help.

Update :

I think I figured that one out, using a 2d array.

have a look at maps [:], they may be a better choice for what you’re doing.
http://grails.asia/groovy-map-tutorial
&|
https://www.tutorialspoint.com/groovy/groovy_maps.htm

1 Like

It did help a lot, Indeed, to work with maps instead of lists. I successfully wrote this one:

def MapofIndexValues = [0: "0", Home: "1", Night: "2", Away: "3", CustomMode1: "4", CustomMode2: "5" ]   
    def IndexValue = MapofIndexValues."$CurrMode"
    IndexValue = IndexValue.toInteger()

but for this one, I’m totally stuck:

def ThermostatIndexValues = [0: 0, Thermostat_1: 1, Thermostat_2: 2, Thermostat_3: 3, Thermostat_4: 4 ]
    def ThermNumber = ThermostatIndexValues.device

it returns a null value, whichever format I convert the “device” variable. FYI : device = state.device = device.evt in setpointhandler().

I can’t figure out what I’m missing, since I’m pretty sure that evt.device is supposed to be a string…

well yea, your ThermostatIndexValues map contains no such attribute named device…
evt is also an object…

From that second code snip that you’ve posted, I have no idea what you’re trying to do…

My apologies.

def device = evt.device

Here is what works, as a simple list:
def CurrentThermostat = device ?: [null, Thermostat_1, Thermostat_2, Thermostat_3, Thermostat_4]
log.info “-----------------------------------------------------------------------------------------CurrentThermostat = $CurrentThermostat”

This returns the correct device event. So Thermostat_1 etc. are just thermostats in settings, just like the modes are modes in settings in the previous snip.

I am still just trying to get a number assigned to a device so I can after that map with other values such as :

for device number 1 and mode number 2, do this, for device number x and mode number y, do that.

The whole thing comes from the fact that I’m working on overrides so a manual setting of the temperature directly on the thermostat will be identified as such in a program that has values for different thermostats and different modes.

I’m really stuck here because I don’t understand why the first snip works and not the second one (assuming I tried pretty much every combinations of formats in the map like “$Thermostat_1” instead of Thermostat_1 or “1” instead of 1… etc…

the whole mess is here:

here’s part, if not all the issue:

if(device == “${Thermostat_1}” << the device name is never going to = the device object…

device is evt.device which represents the actual device, however only the default value (displayName) is assigned to the variable,
use evt.displayName for clarity IE device = evt.displayName
then in the IF use device=="${Thermostat_1.displayName }"

you need to get a good grasp of objects vs their attributes, which is not as easy as it sounds sometimes.

No problem with this code, the one I always used so far, always either declaring String device = evt.device or using evt.displayName, it works either way since the attribute is a string anyway, if I’m correct. Here is what I wanted to bring to using lists and maps instead, for the sake of learning only:

 if(evt.displayName == "${Thermostat_1}"){
        log.debug "evt.device 1 is $evt.device"
        ThermNumber = 1
        if(AltSensor_1){
            AltSENSOR = true
            log.debug "AltSENSOR is $AltSENSOR"
            AlternativeSensor1()
        }
    }
    else if(evt.displayName == "${Thermostat_2}"){
        log.debug "evt.device 2 is $evt.device"
        ThermNumber = 2
        if(AltSensor_2){
            AltSENSOR = true
            log.debug "AltSENSOR is $AltSENSOR"
            AlternativeSensor2()
        }
    } 
    else if(evt.displayName == "${Thermostat_3}"){
        log.debug "evt.device 3 is $evt.device"
        ThermNumber = 3
        if(AltSensor_3){
            AltSENSOR = true
            log.debug "AltSENSOR is $AltSENSOR"
            AlternativeSensor1()
        }
    } 
    else if(evt.displayName == "${Thermostat_4}"){
        log.debug "evt.device 4 is $evt.device"
        AltSENSOR = false // always false because this option doesn't exist for this thermostat number
        ThermNumber = 4
    }
    log.info "-----------------------------------------------------------------------------------------ThermNumber = $ThermNumber"

I am giving up for today. I successfully, though, thanks to you, brought many other conditions to simple lists and maps, and I’m veeeery grateful for it! I’m totally lost though regarding the fact that this one works :

def MapofIndexValues = [0: "0", Home: "1", Night: "2", Away: "3", CustomMode1: "4", CustomMode2: "5" ]   
    def IndexValue = MapofIndexValues."$CurrMode"
    IndexValue = IndexValue.toInteger()
    log.info "-----------------------------------------------------------------------------------------IndexValue = $IndexValue"

while I could not do the same with the devices, even using evt.displayName… Always get a null value when I try anything close to this:

def MapThermostat_Index = [0: "0",  Thermostat_1: "1", Thermostat_2: "2", Thermostat_3: "3", Thermostat_4: "4" ]   
    def ThermNumber = MapThermostat_Index ."${evt.displayName}"
    ThermNumber = ThermNumber.toInteger()
    log.info "-----------------------------------------------------------------------------------------ThermNumber = $ThermNumber "

It’ll remain a mystery to me… for now. And if the answer is in your posts… well, I’ll have to read them again once rested! :slight_smile:
But, again, many, many, many thanks! :smiley:

https://github.com/SmartThingsCommunity/SmartThingsPublic/pull/1664

You’re missing the point. Thermostat_x represents a list of selected device objects, even if only one is selected.
Add that to your log.debug line and you’ll see what I mean…
Counting on the default attribute value for an object will eventually bite you in the ass…
It’s your code, so you can do what you want however.
Thermostat_x [0].displayName is what, safer yet is is to wrap that in case it’s null, unless that’s someplace else

1 Like

multiple: true… Yes! What an idiot, each thermostat value is a an array, indeed! Thanks! :slight_smile:

I wouldn’t say your an idiot, groovy magic is anything but intuitive, plop that on st’s schema, and it’s even less so…
The key to it is understanding object types and the methods to manipulate them.

1 Like

Last night I worked it around using find { it.key == “$devicetolookfor”} in another app and it happened to work also with the thermostats, providing I added “.value” to the variable coming out of this operation, so (if I understand properly, which I’m still uncertain of), searching for a value instead of an object was the trick, since the object was… an array? Is an array an object? Lol I’m lost… haha :smile: ight? hot, cold? It works now, but I am trying to get it more accurately. Is an array a series of objects or a series of values refering to objects? Or is it that an array can be a series of values referring to other arrays themselves containing values? In that case, what is the object? In that case a value always / or can refer to an object? Ignorance is so good when you’re aware of it! (please do not look for which field I work in, otherwise you’re going to laugh here… )

Thermostat_1[0] is an object and Thermostat_1 is a value, or the other way around?

I’m really taking advantage of your kindness here! :smiley: It’s ok to discard! Not everybody has as much vacation time as I do!!!

Thermostat_1 (from prefs) is a list of objects, in this case devices. Thermostat_1[0] is the first device in that list…
Sure you can search through a list with one element in it, but in your case you only have one device in there anyway, so you can just refer to it directly using [0]… objects have attributes and values. It’s crucial to understand what objects have which attributes, so you can use the values assigned to those attributes.

I’ll leave as an excercize for you to learn how to iterate through all an objects attributes (properties) and expose the assigned values.
Have a search for groovy object properties…
Then learn about the groovy each loops…

I frequently use “device.hasCommand()”, “device.hasAttribute()” or even “device.hasCapability”

so as a quick guess I’d say that in order to list attributes, commands and capabilities, I’d write something close to this:

log.debug “device.AllAttributes()” or “device.*Attributes” and so on for commands and Capabilities.