DeviceHandler state map changing type of keys?


(Pedro Toledo Correa) #1

Hi,

I have a DeviceHandler that performs some operations that I find too heavy, so I store those results on a state variable (map) and I reuse that data while valid for my purposes. The thing is, the first time I store and use this data the map keys are stored as numbers, but when I reuse this data the keys need to be accessed as if they where strings.

Is this an expected behavior? Has somebody encountered a similar problem?

If there is no solution, or this is an expected behavior, I need to choose between changing all the buffer creation use of keys or making a duplicate of the code when using the data (depending if it comes from the calculation or the buffer). I would rather find a way to achieve a predictable behavior :persevere:.

This is an example of my code:

def problem() {
  if(state.buff == null || state.buff["myMap"] == null){
    if(state.buff == null){
      state.buff=[:]
    }
    state.buff["myMap"]=[:]
    state.buff["myMap"][1] = "Bla bla bla ... heavy thing 1"
    state.buff["myMap"][2] = "Ble ble ble ... heavy thing 2"
  }
  // This works only the time I create the buffer,
  // then the values are read as null
  log.debug "Buffer content: ${state.buff["myMap"][1]} ${state.buff["myMap"][2]}

  // This is read as null values the first time, but
  // works when I use the previous state values by avoid the previous "if"
  log.debug "Buffer content: ${state.buff["myMap"]["1"]} ${state.buff["myMap"]["2"]}
}

(www.rboyapps.com - Make your home your butler!) #2

The state variable is basically a JSON map and if I’m correct keys cannot be numbers but have to be a string, if I understood your question correctly


(Pedro Toledo Correa) #3

Hy @RBoy,

Yes… I agree. That’s why I always assumed that if I put an int on the addressing (as on lines 7 and 8) it was going to get transformed to a string and used this way from the beginning; nevertheless, this example show that there seems to be a difference if accessing the field with a number or a string (as exemplified by the different behavior comparing lines 12 and 16 that should be equivalent); then, I do not know if I am doing something wrong, if this is a feature or there is something weird happening on this case.


(www.rboyapps.com - Make your home your butler!) #4

Nope, I’m wrong, the map does save the key as a number, you can check it on groovy console by defining state as a [:]

This is what state looks like

[‘buff’:[‘myMap’:[1:‘Bla bla bla … heavy thing 1’, 2:‘Ble ble ble … heavy thing 2’]]]


(Pedro Toledo Correa) #5

In that case… can you differentiate a buff[“myMap”][1] from a buff[“myMap”][“1”] as different values? Or you access the values indifferently of the type of the index while they correspond to the same string? This is the behavior that I find weird, how buff[“myMap”][1] and buff[“myMap”][“1”] can render to different values, but when one works the other answers “null”.


(www.rboyapps.com - Make your home your butler!) #6

That’s correct, buff[“mymap”][1] is different from buff[“mymap”][“1”]

Run this code in groovyconsole.appspot.com and see the difference:

def state = [:]
if(state.buff == null || state.buff["myMap"] == null){     
    if(state.buff == null){       
        state.buff=[:]     
    }     
    state.buff["myMap"]=[:]     
    state.buff["myMap"][1] = "Bla bla bla ... heavy thing 1"     
    state.buff["myMap"][2] = "Ble ble ble ... heavy thing 2"   
    state.buff["myMap"]["1"] = "Bla bla bla ... heavy thing 3"     
    state.buff["myMap"]["2"] = "Ble ble ble ... heavy thing 4"   
}
println "Buffer content: ${state.buff["myMap"][1]} ${state.buff["myMap"][2]}"
println "Buffer content: ${state.buff["myMap"]["1"]} ${state.buff["myMap"]["2"]}"​​​​​​​​​​​​​​​​​​​​

The output is

Buffer content: Bla bla bla … heavy thing 1 Ble ble ble … heavy thing 2
Buffer content: Bla bla bla … heavy thing 3 Ble ble ble … heavy thing 4


(Pedro Toledo Correa) #7

Then the mistery is confirmed… why when I store:

state.buff["myMap"][1] = "Bla bla bla ... heavy thing 1"

During the execution of that time of the function I use it with a number index, but the next time I enter the function the state value needs to be accessed as:

state.buff["myMap"]["1"] = "Bla bla bla ... heavy thing 1"?


(www.rboyapps.com - Make your home your butler!) #8

Well that may be not be the intended behavior. Maybe someone from the ST staff can confirm if that’s the way the state variable is supposed to behave because on groovy console it behaves a little differently.

@Jim @slagle - is this is the expected behavior from the state variable (and consequently from atomicState also)?


(Pedro Toledo Correa) #9

Let’s wait for the ST staff answer to know what could be happening. In the meanwhile I just changed all my keys to strings, but I would rather to use i in place of “${i}” every single time I use an iterator.

PS: @RBoy your groovyconsole is extremely handy! I never though it existed something like that so I never even searched for it. Great hint for testing!


(Pedro Toledo Correa) #10

Well… it seems that we’ll never know… :sob:


(www.rboyapps.com - Make your home your butler!) #11

I think ST’s focussing their efforts on the new API, this may just be in maintenance mode