App Settings device list - using a hash map to get devices for increased speed

I have an app with a device selection option as such:

input "devList", "capability.*",hideWhenEmpty: false, multiple: true, required: false, title: "Devices to publish", submitOnChange: false

Later on I need to access these devices based on an MQTT event so I dont have the device itself. I've made it work by creating a hashmap of the mqttname to the appropriate array location within 'devlist' that i store in the state variable. This way I get much better performance getting the device. My assumption is that this settings input array is only updated when the app config is opened and submitted - in which case I update my indexing. Is this correct?

Thanks!

I'm not really sure what you're asking so I will tell you how state and atomicState work.

For apps, the app instance is loaded and whatever state variables were present last time an instance of the app was loaded are pulled from storage and loaded into memory. So, there is one read from flash (slow) when an app instance is started. You can manipulate the state variables as often as you want during runtime and as long as the size of the state doesn't overflow whatever is allocated to physical RAM for (and who knows what that value is) there are no reads or writes to flash for state (unless of course you page fault and cause swapping). When execution is done the new state is written to flash (slow).

Atomic state is different in that as soon as state changes the first available opportunity to write back to flash is taken so that it is atomic for all instances of the app.

I have a feeling that preferences (your input control) and state (non-atomic) variables behave rather the same way. They're both loaded into memory when the app instance is loaded and not bothered unless the app finishes execution.

Let me rephrase. My main question is - does the preference variable - which in my case is related to 'capabilites.*' (so all devices) ever change outside of the app configuration screen? ie a new device is added. My assumption is that it is a local variable setup with app configuration and therefore it would remain static until the app was configured again. Only when the config page is brought up would the settings list item be updated with any new devices / removed devices thus changing the indexing at that point.

The reasoning behind my question:

This is useful because I need to get the device object regularly given only the name. As is I would have to do a loop on the preferences object doing a string compare on every single name whenever I wanted a device. This is very compute expensive / inefficient. My solution is that while I am updating the device I create a hash and store into state during config. This hash links a device name to the device index within this settings configuration list. This is a much less compute expensive way of finding the device.

Just did some further testing myself and it looks like this list is created/updated upon device selection and is based only on the selected devices so this methodology is safe.

1 Like

I see you got something figured out above (I'd have guessed that the order wouldn't change unless the app was opened, and even then maybe only if you modify the selections--but can definitely tell you that no device would get added to the actual list except by user action), but the above is pretty Java-esque thinking. :slight_smile: In Groovy you have a few Closures that could help you with this without having to loop over everything. One possibility would be something like:

myDeviceInput.find { it.displayName == 'My Switch Device Name' }

I'm not sure what this does under the hood or if it's actually better than you looping yourself (I could imagine an inefficient implementation where this is nothing more than sugary syntax), but I figured it was worth mentioning if you haven't already considered it.

Yeah I saw the .find function but I just assumed it was a less verbose way of doing the loop as I had mentioned. I'd love to know if it is more efficient as it would be a bit more simplistic than using a middle man hash to store the indexes.